Skip to content

Commit 3eeb543

Browse files
Handle fs errors through errors::Handler instead of eprintln and panic
1 parent 6392bc9 commit 3eeb543

File tree

3 files changed

+66
-12
lines changed

3 files changed

+66
-12
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3254,6 +3254,7 @@ dependencies = [
32543254
"minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
32553255
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
32563256
"pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
3257+
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
32573258
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
32583259
]
32593260

src/librustdoc/docfs.rs

+47-8
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@
99
//! needs to read-after-write from a file, then it would be added to this
1010
//! abstraction.
1111
12+
use errors;
13+
14+
use std::cell::RefCell;
1215
use std::fs;
1316
use std::io;
1417
use std::path::Path;
18+
use std::sync::Arc;
19+
use std::sync::mpsc::{channel, Receiver, Sender};
1520

1621
macro_rules! try_err {
1722
($e:expr, $file:expr) => {{
@@ -26,14 +31,45 @@ pub trait PathError {
2631
fn new<P: AsRef<Path>>(e: io::Error, path: P) -> Self;
2732
}
2833

34+
pub struct ErrorStorage {
35+
sender: Sender<Option<String>>,
36+
receiver: Receiver<Option<String>>,
37+
}
38+
39+
impl ErrorStorage {
40+
pub fn new() -> ErrorStorage {
41+
let (sender, receiver) = channel();
42+
ErrorStorage {
43+
sender,
44+
receiver,
45+
}
46+
}
47+
48+
/// Prints all stored errors. Returns the number of printed errors.
49+
pub fn write_errors(&self, diag: &errors::Handler) -> usize {
50+
let mut printed = 0;
51+
drop(self.sender);
52+
53+
for msg in self.receiver.iter() {
54+
if let Some(ref error) = msg {
55+
diag.struct_err(&error).emit();
56+
printed += 1;
57+
}
58+
}
59+
printed
60+
}
61+
}
62+
2963
pub struct DocFS {
3064
sync_only: bool,
65+
errors: Arc<ErrorStorage>,
3166
}
3267

3368
impl DocFS {
34-
pub fn new() -> DocFS {
69+
pub fn new(errors: &Arc<ErrorStorage>) -> DocFS {
3570
DocFS {
3671
sync_only: false,
72+
errors: Arc::clone(errors),
3773
}
3874
}
3975

@@ -59,16 +95,19 @@ impl DocFS {
5995
// be to create the file sync so errors are reported eagerly.
6096
let contents = contents.as_ref().to_vec();
6197
let path = path.as_ref().to_path_buf();
62-
rayon::spawn(move ||
98+
let sender = self.errors.sender.clone();
99+
rayon::spawn(move || {
63100
match fs::write(&path, &contents) {
64-
Ok(_) => (),
101+
Ok(_) => {
102+
sender.send(None)
103+
.expect(&format!("failed to send error on \"{}\"", path.display()));
104+
}
65105
Err(e) => {
66-
// In principle these should get displayed at the top
67-
// level, but just in case, send to stderr as well.
68-
eprintln!("\"{}\": {}", path.display(), e);
69-
panic!("\"{}\": {}", path.display(), e);
106+
sender.send(Some(format!("\"{}\": {}", path.display(), e)))
107+
.expect(&format!("failed to send non-error on \"{}\"", path.display()));
70108
}
71-
});
109+
}
110+
});
72111
Ok(())
73112
} else {
74113
Ok(try_err!(fs::write(&path, contents), path))

src/librustdoc/html/render.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use rustc_data_structures::flock;
6161

6262
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, Mutability};
6363
use crate::config::RenderOptions;
64-
use crate::docfs::{DocFS, PathError};
64+
use crate::docfs::{DocFS, ErrorStorage, PathError};
6565
use crate::doctree;
6666
use crate::fold::DocFolder;
6767
use crate::html::escape::Escape;
@@ -104,7 +104,12 @@ impl error::Error for Error {
104104

105105
impl Display for Error {
106106
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
107-
write!(f, "\"{}\": {}", self.file.display(), self.error)
107+
let file = self.file.display().to_string();
108+
if file.is_empty() {
109+
write!(f, "{}", self.error)
110+
} else {
111+
write!(f, "\"{}\": {}", self.file.display(), self.error)
112+
}
108113
}
109114
}
110115

@@ -547,6 +552,7 @@ pub fn run(mut krate: clean::Crate,
547552
},
548553
_ => PathBuf::new(),
549554
};
555+
let errors = Arc::new(ErrorStorage::new());
550556
let mut scx = SharedContext {
551557
src_root,
552558
passes,
@@ -567,7 +573,7 @@ pub fn run(mut krate: clean::Crate,
567573
static_root_path,
568574
generate_search_filter,
569575
generate_redirect_pages,
570-
fs: DocFS::new(),
576+
fs: DocFS::new(&errors),
571577
};
572578

573579
// If user passed in `--playground-url` arg, we fill in crate name here
@@ -715,7 +721,15 @@ pub fn run(mut krate: clean::Crate,
715721
Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
716722

717723
// And finally render the whole crate's documentation
718-
cx.krate(krate)
724+
let ret = cx.krate(krate);
725+
let nb_errors = errors.write_errors(diag);
726+
if ret.is_err() {
727+
ret
728+
} else if nb_errors > 0 {
729+
Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
730+
} else {
731+
Ok(())
732+
}
719733
}
720734

721735
/// Builds the search index from the collected metadata

0 commit comments

Comments
 (0)