Skip to content

Commit 54b6b03

Browse files
committed
Actually use eyre and get rid of the ad-hoc macros emulating error handling
1 parent 570032b commit 54b6b03

File tree

4 files changed

+88
-106
lines changed

4 files changed

+88
-106
lines changed

tests/compiletest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use colored::*;
22
use regex::Regex;
33
use std::env;
44
use std::path::PathBuf;
5-
use ui_test::{Config, Mode, OutputConflictHandling, color_eyre::Result};
5+
use ui_test::{color_eyre::Result, Config, Mode, OutputConflictHandling};
66

77
fn miri_path() -> PathBuf {
88
PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri")))

ui_test/src/comments.rs

Lines changed: 71 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use regex::Regex;
44

55
use crate::rustc_stderr::Level;
66

7-
use color_eyre::eyre::Result;
7+
use color_eyre::eyre::{bail, ensure, eyre, Result};
88

99
#[cfg(test)]
1010
mod tests;
@@ -66,43 +66,6 @@ impl Condition {
6666
}
6767
}
6868

69-
macro_rules! checked {
70-
($path:expr, $l:expr) => {
71-
let path = $path;
72-
let l = $l;
73-
#[allow(unused_macros)]
74-
macro_rules! exit {
75-
($fmt:expr $$(,$args:expr)*) => {{
76-
eprint!("{}:{l}: ", path.display());
77-
eprintln!($fmt, $$($args,)*);
78-
#[cfg(not(test))]
79-
std::process::exit(1);
80-
#[cfg(test)]
81-
panic!();
82-
}};
83-
}
84-
#[allow(unused_macros)]
85-
macro_rules! check {
86-
($cond:expr, $fmt:expr $$(,$args:expr)*) => {{
87-
if !$cond {
88-
exit!($fmt $$(,$args)*);
89-
}
90-
}};
91-
}
92-
#[allow(unused_macros)]
93-
macro_rules! unwrap {
94-
($cond:expr, $fmt:expr $$(,$args:expr)*) => {{
95-
match $cond {
96-
Some(val) => val,
97-
None => {
98-
exit!($fmt $$(,$args)*);
99-
}
100-
}
101-
}};
102-
}
103-
};
104-
}
105-
10669
impl Comments {
10770
pub(crate) fn parse_file(path: &Path) -> Result<Self> {
10871
let content = std::fs::read_to_string(path)?;
@@ -121,24 +84,36 @@ impl Comments {
12184
let mut fallthrough_to = None;
12285
for (l, line) in content.lines().enumerate() {
12386
let l = l + 1; // enumerate starts at 0, but line numbers start at 1
124-
if let Some((_, command)) = line.split_once("//@") {
125-
let command = command.trim();
126-
if let Some((command, args)) = command.split_once(':') {
127-
this.parse_command_with_args(command, args, path, l);
128-
} else if let Some((command, _comments)) = command.split_once(' ') {
129-
this.parse_command(command, path, l)
130-
} else {
131-
this.parse_command(command, path, l)
132-
}
133-
} else if let Some((_, pattern)) = line.split_once("//~") {
134-
this.parse_pattern(pattern, &mut fallthrough_to, path, l)
135-
} else if let Some((_, pattern)) = line.split_once("//[") {
136-
this.parse_revisioned_pattern(pattern, &mut fallthrough_to, path, l)
87+
this.parse_checked_line(l, &mut fallthrough_to, line).map_err(|err| {
88+
err.wrap_err(format!("{}:{l}: failed to parse annotation", path.display()))
89+
})?;
90+
}
91+
Ok(this)
92+
}
93+
94+
fn parse_checked_line(
95+
&mut self,
96+
l: usize,
97+
fallthrough_to: &mut Option<usize>,
98+
line: &str,
99+
) -> Result<()> {
100+
if let Some((_, command)) = line.split_once("//@") {
101+
let command = command.trim();
102+
if let Some((command, args)) = command.split_once(':') {
103+
self.parse_command_with_args(command, args, l)
104+
} else if let Some((command, _comments)) = command.split_once(' ') {
105+
self.parse_command(command)
137106
} else {
138-
fallthrough_to = None;
107+
self.parse_command(command)
139108
}
109+
} else if let Some((_, pattern)) = line.split_once("//~") {
110+
self.parse_pattern(pattern, fallthrough_to, l)
111+
} else if let Some((_, pattern)) = line.split_once("//[") {
112+
self.parse_revisioned_pattern(pattern, fallthrough_to, l)
113+
} else {
114+
*fallthrough_to = None;
115+
Ok(())
140116
}
141-
Ok(this)
142117
}
143118

144119
/// Parse comments in `content`.
@@ -214,91 +189,86 @@ impl Comments {
214189
Ok(this)
215190
}
216191

217-
fn parse_command_with_args(&mut self, command: &str, args: &str, path: &Path, l: usize) {
218-
checked!(path, l);
192+
fn parse_command_with_args(&mut self, command: &str, args: &str, l: usize) -> Result<()> {
219193
match command {
220194
"revisions" => {
221-
check!(self.revisions.is_none(), "cannot specifiy revisions twice");
195+
ensure!(self.revisions.is_none(), "cannot specifiy revisions twice");
222196
self.revisions = Some(args.split_whitespace().map(|s| s.to_string()).collect());
223197
}
224198
"compile-flags" => {
225199
self.compile_flags.extend(args.split_whitespace().map(|s| s.to_string()));
226200
}
227201
"rustc-env" =>
228202
for env in args.split_whitespace() {
229-
let (k, v) = unwrap!(
230-
env.split_once('='),
231-
"environment variables must be key/value pairs separated by a `=`"
232-
);
203+
let (k, v) = env.split_once('=').ok_or_else(|| {
204+
eyre!("environment variables must be key/value pairs separated by a `=`")
205+
})?;
233206
self.env_vars.push((k.to_string(), v.to_string()));
234207
},
235208
"normalize-stderr-test" => {
236-
let (from, to) =
237-
unwrap!(args.split_once("->"), "normalize-stderr-test needs a `->`");
209+
let (from, to) = args
210+
.split_once("->")
211+
.ok_or_else(|| eyre!("normalize-stderr-test needs a `->`"))?;
238212
let from = from.trim().trim_matches('"');
239213
let to = to.trim().trim_matches('"');
240-
let from = unwrap!(Regex::new(from).ok(), "invalid regex");
214+
let from = Regex::new(from).ok().ok_or_else(|| eyre!("invalid regex"))?;
241215
self.normalize_stderr.push((from, to.to_string()));
242216
}
243217
"error-pattern" => {
244-
check!(
218+
ensure!(
245219
self.error_pattern.is_none(),
246220
"cannot specifiy error_pattern twice, previous: {:?}",
247221
self.error_pattern
248222
);
249223
self.error_pattern = Some((args.trim().to_string(), l));
250224
}
251225
// Maybe the user just left a comment explaining a command without arguments
252-
_ => self.parse_command(command, path, l),
226+
_ => self.parse_command(command)?,
253227
}
228+
Ok(())
254229
}
255230

256-
fn parse_command(&mut self, command: &str, path: &Path, l: usize) {
257-
checked!(path, l);
258-
231+
fn parse_command(&mut self, command: &str) -> Result<()> {
259232
if let Some(s) = command.strip_prefix("ignore-") {
260233
self.ignore.push(Condition::parse(s));
261-
return;
234+
return Ok(());
262235
}
263236

264237
if let Some(s) = command.strip_prefix("only-") {
265238
self.only.push(Condition::parse(s));
266-
return;
239+
return Ok(());
267240
}
268241

269242
if command.starts_with("stderr-per-bitwidth") {
270-
check!(!self.stderr_per_bitwidth, "cannot specifiy stderr-per-bitwidth twice");
243+
ensure!(!self.stderr_per_bitwidth, "cannot specifiy stderr-per-bitwidth twice");
271244
self.stderr_per_bitwidth = true;
272-
return;
245+
return Ok(());
273246
}
274247

275-
exit!("unknown command {command}");
248+
bail!("unknown command {command}");
276249
}
277250

278251
fn parse_pattern(
279252
&mut self,
280253
pattern: &str,
281254
fallthrough_to: &mut Option<usize>,
282-
path: &Path,
283255
l: usize,
284-
) {
285-
self.parse_pattern_inner(pattern, fallthrough_to, None, path, l)
256+
) -> Result<()> {
257+
self.parse_pattern_inner(pattern, fallthrough_to, None, l)
286258
}
287259

288260
fn parse_revisioned_pattern(
289261
&mut self,
290262
pattern: &str,
291263
fallthrough_to: &mut Option<usize>,
292-
path: &Path,
293264
l: usize,
294-
) {
295-
checked!(path, l);
265+
) -> Result<()> {
296266
let (revision, pattern) =
297-
unwrap!(pattern.split_once(']'), "`//[` without corresponding `]`");
267+
pattern.split_once(']').ok_or_else(|| eyre!("`//[` without corresponding `]`"))?;
298268
if let Some(pattern) = pattern.strip_prefix('~') {
299-
self.parse_pattern_inner(pattern, fallthrough_to, Some(revision.to_owned()), path, l)
269+
self.parse_pattern_inner(pattern, fallthrough_to, Some(revision.to_owned()), l)
300270
} else {
301-
exit!("revisioned pattern must have `~` following the `]`");
271+
bail!("revisioned pattern must have `~` following the `]`");
302272
}
303273
}
304274

@@ -308,21 +278,25 @@ impl Comments {
308278
pattern: &str,
309279
fallthrough_to: &mut Option<usize>,
310280
revision: Option<String>,
311-
path: &Path,
312281
l: usize,
313-
) {
314-
checked!(path, l);
282+
) -> Result<()> {
315283
// FIXME: check that the error happens on the marked line
316284

317-
let (match_line, pattern) = match unwrap!(pattern.chars().next(), "no pattern specified") {
318-
'|' =>
319-
(*unwrap!(fallthrough_to, "`//~|` pattern without preceding line"), &pattern[1..]),
320-
'^' => {
321-
let offset = pattern.chars().take_while(|&c| c == '^').count();
322-
(l - offset, &pattern[offset..])
323-
}
324-
_ => (l, pattern),
325-
};
285+
let (match_line, pattern) =
286+
match pattern.chars().next().ok_or_else(|| eyre!("no pattern specified"))? {
287+
'|' =>
288+
(
289+
*fallthrough_to
290+
.as_mut()
291+
.ok_or_else(|| eyre!("`//~|` pattern without preceding line"))?,
292+
&pattern[1..],
293+
),
294+
'^' => {
295+
let offset = pattern.chars().take_while(|&c| c == '^').count();
296+
(l - offset, &pattern[offset..])
297+
}
298+
_ => (l, pattern),
299+
};
326300

327301
let (level, pattern) = match pattern.trim_start().split_once(|c| matches!(c, ':' | ' ')) {
328302
None => (None, pattern),
@@ -335,7 +309,7 @@ impl Comments {
335309

336310
let matched = pattern.trim().to_string();
337311

338-
check!(!matched.is_empty(), "no pattern specified");
312+
ensure!(!matched.is_empty(), "no pattern specified");
339313

340314
*fallthrough_to = Some(match_line);
341315

@@ -346,5 +320,7 @@ impl Comments {
346320
definition_line: l,
347321
line: match_line,
348322
});
323+
324+
Ok(())
349325
}
350326
}

ui_test/src/comments/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use std::{path::Path, panic::catch_unwind};
1+
use std::path::Path;
22

33
use super::Comments;
44

5-
use color_eyre::eyre::{Result, bail};
65
use crate::tests::init;
6+
use color_eyre::eyre::{bail, Result};
77

88
#[test]
99
fn parse_simple_comment() -> Result<()> {
@@ -48,8 +48,8 @@ fn parse_slash_slash_at_fail() -> Result<()> {
4848
use std::mem;
4949
5050
";
51-
match catch_unwind(|| Comments::parse(Path::new("<dummy>"), s)) {
52-
Ok(_) => bail!("expected parsing to panic"),
51+
match Comments::parse(Path::new("<dummy>"), s) {
52+
Ok(_) => bail!("expected parsing to fail"),
5353
Err(_) => Ok(()),
5454
}
5555
}

ui_test/src/lib.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ use std::process::{Command, ExitStatus};
77
use std::sync::atomic::{AtomicUsize, Ordering};
88
use std::sync::Mutex;
99

10+
pub use color_eyre;
11+
use color_eyre::eyre::Result;
1012
use colored::*;
1113
use comments::ErrorMatch;
1214
use regex::Regex;
1315
use rustc_stderr::{Level, Message};
14-
use color_eyre::eyre::Result;
15-
pub use color_eyre;
1616

1717
use crate::comments::{Comments, Condition};
1818

@@ -68,7 +68,7 @@ pub fn run_tests(config: Config) -> Result<()> {
6868
let ignored = AtomicUsize::default();
6969
let filtered = AtomicUsize::default();
7070

71-
crossbeam::scope(|s| {
71+
crossbeam::scope(|s| -> Result<()> {
7272
// Create a thread that is in charge of walking the directory and submitting jobs.
7373
// It closes the channel when it is done.
7474
s.spawn(|_| {
@@ -94,9 +94,11 @@ pub fn run_tests(config: Config) -> Result<()> {
9494
drop(submit);
9595
});
9696

97+
let mut threads = vec![];
98+
9799
// Create N worker threads that receive files to test.
98100
for _ in 0..std::thread::available_parallelism().unwrap().get() {
99-
s.spawn(|_| -> Result<()> {
101+
threads.push(s.spawn(|_| -> Result<()> {
100102
for path in &receive {
101103
if !config.path_filter.is_empty() {
102104
let path_display = path.display().to_string();
@@ -145,10 +147,14 @@ pub fn run_tests(config: Config) -> Result<()> {
145147
}
146148
}
147149
Ok(())
148-
});
150+
}));
151+
}
152+
for thread in threads {
153+
thread.join().unwrap()?;
149154
}
155+
Ok(())
150156
})
151-
.unwrap();
157+
.unwrap()?;
152158

153159
// Print all errors in a single thread to show reliable output
154160
let failures = failures.into_inner().unwrap();

0 commit comments

Comments
 (0)