Skip to content

Commit 456a2fb

Browse files
committed
Migrate the error_codes check to diagnostics
1 parent 91590f9 commit 456a2fb

File tree

2 files changed

+50
-78
lines changed

2 files changed

+50
-78
lines changed

src/tools/tidy/src/error_codes.rs

Lines changed: 48 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::path::Path;
2222

2323
use regex::Regex;
2424

25+
use crate::diagnostics::{DiagCtx, RunningCheck};
2526
use crate::walk::{filter_dirs, walk, walk_many};
2627

2728
const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/lib.rs";
@@ -35,71 +36,50 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E07
3536
const IGNORE_UI_TEST_CHECK: &[&str] =
3637
&["E0461", "E0465", "E0514", "E0554", "E0640", "E0717", "E0729"];
3738

38-
macro_rules! verbose_print {
39-
($verbose:expr, $($fmt:tt)*) => {
40-
if $verbose {
41-
println!("{}", format_args!($($fmt)*));
42-
}
43-
};
44-
}
45-
46-
pub fn check(
47-
root_path: &Path,
48-
search_paths: &[&Path],
49-
verbose: bool,
50-
ci_info: &crate::CiInfo,
51-
bad: &mut bool,
52-
) {
53-
let mut errors = Vec::new();
39+
pub fn check(root_path: &Path, search_paths: &[&Path], ci_info: &crate::CiInfo, diag_ctx: DiagCtx) {
40+
let mut check = diag_ctx.start_check("error_codes");
5441

5542
// Check that no error code explanation was removed.
56-
check_removed_error_code_explanation(ci_info, bad);
43+
check_removed_error_code_explanation(ci_info, &mut check);
5744

5845
// Stage 1: create list
59-
let error_codes = extract_error_codes(root_path, &mut errors);
60-
if verbose {
61-
println!("Found {} error codes", error_codes.len());
62-
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
63-
}
46+
let error_codes = extract_error_codes(root_path, &mut check);
47+
check.verbose_msg(format!("Found {} error codes", error_codes.len()));
48+
check.verbose_msg(format!("Highest error code: `{}`", error_codes.iter().max().unwrap()));
6449

6550
// Stage 2: check list has docs
66-
let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose);
51+
let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut check);
6752

6853
// Stage 3: check list has UI tests
69-
check_error_codes_tests(root_path, &error_codes, &mut errors, verbose, &no_longer_emitted);
54+
check_error_codes_tests(root_path, &error_codes, &mut check, &no_longer_emitted);
7055

7156
// Stage 4: check list is emitted by compiler
72-
check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose);
73-
74-
// Print any errors.
75-
for error in errors {
76-
tidy_error!(bad, "{}", error);
77-
}
57+
check_error_codes_used(search_paths, &error_codes, &mut check, &no_longer_emitted);
7858
}
7959

80-
fn check_removed_error_code_explanation(ci_info: &crate::CiInfo, bad: &mut bool) {
60+
fn check_removed_error_code_explanation(ci_info: &crate::CiInfo, check: &mut RunningCheck) {
8161
let Some(base_commit) = &ci_info.base_commit else {
82-
eprintln!("Skipping error code explanation removal check");
62+
check.verbose_msg("Skipping error code explanation removal check");
8363
return;
8464
};
8565
let Some(diff) = crate::git_diff(base_commit, "--name-status") else {
86-
*bad = true;
87-
eprintln!("removed error code explanation tidy check: Failed to run git diff");
66+
check.error(format!("removed error code explanation: Failed to run git diff"));
8867
return;
8968
};
9069
if diff.lines().any(|line| {
9170
line.starts_with('D') && line.contains("compiler/rustc_error_codes/src/error_codes/")
9271
}) {
93-
*bad = true;
94-
eprintln!("tidy check error: Error code explanations should never be removed!");
95-
eprintln!("Take a look at E0001 to see how to handle it.");
72+
check.error(format!(
73+
r#"Error code explanations should never be removed!
74+
Take a look at E0001 to see how to handle it."#
75+
));
9676
return;
9777
}
98-
println!("No error code explanation was removed!");
78+
check.verbose_msg("No error code explanation was removed!");
9979
}
10080

10181
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
102-
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
82+
fn extract_error_codes(root_path: &Path, check: &mut RunningCheck) -> Vec<String> {
10383
let path = root_path.join(Path::new(ERROR_CODES_PATH));
10484
let file =
10585
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
@@ -117,7 +97,7 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
11797
// Extract the error code from the line. Emit a fatal error if it is not in the correct
11898
// format.
11999
let Some(split_line) = split_line else {
120-
errors.push(format!(
100+
check.error(format!(
121101
"{path}:{line_index}: Expected a line with the format `Eabcd: abcd, \
122102
but got \"{line}\" without a `:` delimiter",
123103
));
@@ -128,8 +108,9 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
128108

129109
// If this is a duplicate of another error code, emit a fatal error.
130110
if error_codes.contains(&err_code) {
131-
errors
132-
.push(format!("{path}:{line_index}: Found duplicate error code: `{err_code}`"));
111+
check.error(format!(
112+
"{path}:{line_index}: Found duplicate error code: `{err_code}`"
113+
));
133114
continue;
134115
}
135116

@@ -140,14 +121,14 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
140121
// Ensure that the line references the correct markdown file.
141122
let rest = split_line.1.split_once(',');
142123
let Some(rest) = rest else {
143-
errors.push(format!(
124+
check.error(format!(
144125
"{path}:{line_index}: Expected a line with the format `Eabcd: abcd, \
145126
but got \"{line}\" without a `,` delimiter",
146127
));
147128
continue;
148129
};
149130
if error_num_as_str != rest.0.trim() {
150-
errors.push(format!(
131+
check.error(format!(
151132
"{path}:{line_index}: `{}:` should be followed by `{},` but instead found `{}` in \
152133
`compiler/rustc_error_codes/src/lib.rs`",
153134
err_code,
@@ -157,7 +138,7 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
157138
continue;
158139
}
159140
if !rest.1.trim().is_empty() && !rest.1.trim().starts_with("//") {
160-
errors.push(format!("{path}:{line_index}: should only have one error per line"));
141+
check.error(format!("{path}:{line_index}: should only have one error per line"));
161142
continue;
162143
}
163144

@@ -172,8 +153,7 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
172153
fn check_error_codes_docs(
173154
root_path: &Path,
174155
error_codes: &[String],
175-
errors: &mut Vec<String>,
176-
verbose: bool,
156+
check: &mut RunningCheck,
177157
) -> Vec<String> {
178158
let docs_path = root_path.join(Path::new(ERROR_DOCS_PATH));
179159

@@ -184,7 +164,7 @@ fn check_error_codes_docs(
184164

185165
// Error if the file isn't markdown.
186166
if path.extension() != Some(OsStr::new("md")) {
187-
errors.push(format!(
167+
check.error(format!(
188168
"Found unexpected non-markdown file in error code docs directory: {}",
189169
path.display()
190170
));
@@ -196,7 +176,7 @@ fn check_error_codes_docs(
196176
let err_code = filename.unwrap().0; // `unwrap` is ok because we know the filename is in the correct format.
197177

198178
if error_codes.iter().all(|e| e != err_code) {
199-
errors.push(format!(
179+
check.error(format!(
200180
"Found valid file `{}` in error code docs directory without corresponding \
201181
entry in `rustc_error_codes/src/lib.rs`",
202182
path.display()
@@ -208,36 +188,34 @@ fn check_error_codes_docs(
208188
check_explanation_has_doctest(contents, err_code);
209189

210190
if emit_ignore_warning {
211-
verbose_print!(
212-
verbose,
191+
check.verbose_msg(format!(
213192
"warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \
214193
`IGNORE_DOCTEST_CHECK` constant instead."
215-
);
194+
));
216195
}
217196

218197
if no_longer_emitted {
219198
no_longer_emitted_codes.push(err_code.to_owned());
220199
}
221200

222201
if !found_code_example {
223-
verbose_print!(
224-
verbose,
202+
check.verbose_msg(format!(
225203
"warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \
226204
(even if untested)."
227-
);
205+
));
228206
return;
229207
}
230208

231209
let test_ignored = IGNORE_DOCTEST_CHECK.contains(&err_code);
232210

233211
// Check that the explanation has a doctest, and if it shouldn't, that it doesn't
234212
if !found_proper_doctest && !test_ignored {
235-
errors.push(format!(
213+
check.error(format!(
236214
"`{}` doesn't use its own error code in compile_fail example",
237215
path.display(),
238216
));
239217
} else if found_proper_doctest && test_ignored {
240-
errors.push(format!(
218+
check.error(format!(
241219
"`{}` has a compile_fail doctest with its own error code, it shouldn't \
242220
be listed in `IGNORE_DOCTEST_CHECK`",
243221
path.display(),
@@ -289,8 +267,7 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo
289267
fn check_error_codes_tests(
290268
root_path: &Path,
291269
error_codes: &[String],
292-
errors: &mut Vec<String>,
293-
verbose: bool,
270+
check: &mut RunningCheck,
294271
no_longer_emitted: &[String],
295272
) {
296273
let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH));
@@ -299,15 +276,14 @@ fn check_error_codes_tests(
299276
let test_path = tests_path.join(format!("{code}.stderr"));
300277

301278
if !test_path.exists() && !IGNORE_UI_TEST_CHECK.contains(&code.as_str()) {
302-
verbose_print!(
303-
verbose,
279+
check.verbose_msg(format!(
304280
"warning: Error code `{code}` needs to have at least one UI test in the `tests/error-codes/` directory`!"
305-
);
281+
));
306282
continue;
307283
}
308284
if IGNORE_UI_TEST_CHECK.contains(&code.as_str()) {
309285
if test_path.exists() {
310-
errors.push(format!(
286+
check.error(format!(
311287
"Error code `{code}` has a UI test in `tests/ui/error-codes/{code}.rs`, it shouldn't be listed in `EXEMPTED_FROM_TEST`!"
312288
));
313289
}
@@ -317,11 +293,10 @@ fn check_error_codes_tests(
317293
let file = match fs::read_to_string(&test_path) {
318294
Ok(file) => file,
319295
Err(err) => {
320-
verbose_print!(
321-
verbose,
296+
check.verbose_msg(format!(
322297
"warning: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}",
323298
test_path.display()
324-
);
299+
));
325300
continue;
326301
}
327302
};
@@ -343,10 +318,9 @@ fn check_error_codes_tests(
343318
}
344319

345320
if !found_code {
346-
verbose_print!(
347-
verbose,
321+
check.verbose_msg(format!(
348322
"warning: Error code `{code}` has a UI test file, but doesn't contain its own error code!"
349-
);
323+
));
350324
}
351325
}
352326
}
@@ -355,9 +329,8 @@ fn check_error_codes_tests(
355329
fn check_error_codes_used(
356330
search_paths: &[&Path],
357331
error_codes: &[String],
358-
errors: &mut Vec<String>,
332+
check: &mut RunningCheck,
359333
no_longer_emitted: &[String],
360-
verbose: bool,
361334
) {
362335
// Search for error codes in the form `E0123`.
363336
let regex = Regex::new(r#"\bE\d{4}\b"#).unwrap();
@@ -384,7 +357,7 @@ fn check_error_codes_used(
384357

385358
if !error_codes.contains(&error_code) {
386359
// This error code isn't properly defined, we must error.
387-
errors.push(format!("Error code `{error_code}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/lib.rs`."));
360+
check.error(format!("Error code `{error_code}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/lib.rs`."));
388361
continue;
389362
}
390363

@@ -397,7 +370,7 @@ fn check_error_codes_used(
397370

398371
for code in error_codes {
399372
if !found_codes.contains(code) && !no_longer_emitted.contains(code) {
400-
errors.push(format!(
373+
check.error(format!(
401374
"Error code `{code}` exists, but is not emitted by the compiler!\n\
402375
Please mark the code as no longer emitted by adding the following note to the top of the `EXXXX.md` file:\n\
403376
`#### Note: this error code is no longer emitted by the compiler`\n\
@@ -406,10 +379,9 @@ fn check_error_codes_used(
406379
}
407380

408381
if found_codes.contains(code) && no_longer_emitted.contains(code) {
409-
verbose_print!(
410-
verbose,
382+
check.verbose_msg(format!(
411383
"warning: Error code `{code}` is used when it's marked as \"no longer emitted\""
412-
);
384+
));
413385
}
414386
}
415387
}

src/tools/tidy/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,15 @@ fn main() {
118118
check!(unknown_revision, &tests_path);
119119

120120
// Checks that only make sense for the compiler.
121-
// check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose, &ci_info);
121+
check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], &ci_info);
122122
// check!(fluent_alphabetical, &compiler_path, bless);
123123
// check!(fluent_period, &compiler_path);
124124
// check!(fluent_lowercase, &compiler_path);
125125
// check!(target_policy, &root_path);
126126
// check!(gcc_submodule, &root_path, &compiler_path);
127127

128128
// Checks that only make sense for the std libs.
129-
// check!(pal, &library_path);
129+
check!(pal, &library_path);
130130

131131
// Checks that need to be done for both the compiler and std libraries.
132132
check!(unit_tests, &src_path, false);

0 commit comments

Comments
 (0)