Skip to content

Commit 20a6938

Browse files
committed
Auto merge of #28683 - GuillaumeGomez:rustdoc_error, r=alexcrichton
This PR solves the following issues (or at least help users to understand the problem): ```Rust #![crate_name = "b"] #![crate_type = "rlib"] pub fn his_function_has_a_very_long_name_and_should_make_cargo_doc_explodes_because_it_will_want_to_make_a_filename_with_it_in_excess_of_the_max_filename_length_for_most_filesystem_this_is_not_yet_long_enough_i_need_moreis_function_has_a_very_long_name_and_should_make_cargo_doc_explodes_because_it_will_want_to_make_a_filename_with_it_in_excess_of_the_max_filename_length_for_most_filesystem_this_is_not_yet_long_enough_i_need_more_() {} ``` ```Rust #![crate_name = "b"] #![crate_type = "rlib"] pub struct his_function_has_a_very_long_name_and_should_make_cargo_doc_explodes_because_it_will_want_to_make_a_filename_with_it_in_excess_of_the_max_filename_length_for_most_filesystem_this_is_not_yet_long_enough_i_need_moreis_function_has_a_very_long_name_and_should_make_cargo_doc_explodes_because_it_will_want_to_make_a_filename_with_it_in_excess_of_the_max_filename_length_for_most_filesystem_this_is_not_yet_long_enough_i_need_more_; ``` For the maximum filename length chosen, @gkoz gave me [this link](http://unix.stackexchange.com/a/32834).
2 parents be91042 + 42c01d7 commit 20a6938

File tree

1 file changed

+107
-64
lines changed

1 file changed

+107
-64
lines changed

src/librustdoc/html/render.rs

+107-64
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ use std::cell::RefCell;
3939
use std::cmp::Ordering;
4040
use std::collections::{BTreeMap, HashMap, HashSet};
4141
use std::default::Default;
42-
use std::fmt;
42+
use std::error;
43+
use std::fmt::{self, Display, Formatter};
4344
use std::fs::{self, File};
4445
use std::io::prelude::*;
4546
use std::io::{self, BufWriter, BufReader};
@@ -145,6 +146,42 @@ impl Impl {
145146
}
146147
}
147148

149+
#[derive(Debug)]
150+
pub struct Error {
151+
file: PathBuf,
152+
error: io::Error,
153+
}
154+
155+
impl error::Error for Error {
156+
fn description(&self) -> &str {
157+
self.error.description()
158+
}
159+
}
160+
161+
impl Display for Error {
162+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
163+
write!(f, "\"{}\": {}", self.file.display(), self.error)
164+
}
165+
}
166+
167+
impl Error {
168+
pub fn new(e: io::Error, file: &Path) -> Error {
169+
Error {
170+
file: file.to_path_buf(),
171+
error: e,
172+
}
173+
}
174+
}
175+
176+
macro_rules! try_err {
177+
($e:expr, $file:expr) => ({
178+
match $e {
179+
Ok(e) => e,
180+
Err(e) => return Err(Error::new(e, $file)),
181+
}
182+
})
183+
}
184+
148185
/// This cache is used to store information about the `clean::Crate` being
149186
/// rendered in order to provide more useful documentation. This contains
150187
/// information like all implementors of a trait, all traits a type implements,
@@ -310,7 +347,7 @@ thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> =
310347
pub fn run(mut krate: clean::Crate,
311348
external_html: &ExternalHtml,
312349
dst: PathBuf,
313-
passes: HashSet<String>) -> io::Result<()> {
350+
passes: HashSet<String>) -> Result<(), Error> {
314351
let src_root = match krate.src.parent() {
315352
Some(p) => p.to_path_buf(),
316353
None => PathBuf::new(),
@@ -333,7 +370,7 @@ pub fn run(mut krate: clean::Crate,
333370
issue_tracker_base_url: None,
334371
};
335372

336-
try!(mkdir(&cx.dst));
373+
try_err!(mkdir(&cx.dst), &cx.dst);
337374

338375
// Crawl the crate attributes looking for attributes which control how we're
339376
// going to emit HTML
@@ -435,7 +472,7 @@ pub fn run(mut krate: clean::Crate,
435472
krate = cache.fold_crate(krate);
436473

437474
// Build our search index
438-
let index = try!(build_index(&krate, &mut cache));
475+
let index = build_index(&krate, &mut cache);
439476

440477
// Freeze the cache now that the index has been built. Put an Arc into TLS
441478
// for future parallelization opportunities
@@ -450,7 +487,7 @@ pub fn run(mut krate: clean::Crate,
450487
cx.krate(krate)
451488
}
452489

453-
fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
490+
fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
454491
// Build the search index from the collected metadata
455492
let mut nodeid_to_pathid = HashMap::new();
456493
let mut pathid_to_nodeid = Vec::new();
@@ -477,7 +514,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
477514
},
478515
None => {}
479516
}
480-
};
517+
}
481518

482519
// Reduce `NodeId` in paths into smaller sequential numbers,
483520
// and prune the paths that do not appear in the index.
@@ -498,7 +535,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
498535

499536
// Collect the index into a string
500537
let mut w = io::Cursor::new(Vec::new());
501-
try!(write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name));
538+
write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name).unwrap();
502539

503540
let mut lastpath = "".to_string();
504541
for (i, item) in cache.search_index.iter().enumerate() {
@@ -512,58 +549,61 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
512549
};
513550

514551
if i > 0 {
515-
try!(write!(&mut w, ","));
552+
write!(&mut w, ",").unwrap();
516553
}
517-
try!(write!(&mut w, r#"[{},"{}","{}",{}"#,
518-
item.ty as usize, item.name, path,
519-
item.desc.to_json().to_string()));
554+
write!(&mut w, r#"[{},"{}","{}",{}"#,
555+
item.ty as usize, item.name, path,
556+
item.desc.to_json().to_string()).unwrap();
520557
match item.parent {
521558
Some(nodeid) => {
522559
let pathid = *nodeid_to_pathid.get(&nodeid).unwrap();
523-
try!(write!(&mut w, ",{}", pathid));
560+
write!(&mut w, ",{}", pathid).unwrap();
524561
}
525-
None => try!(write!(&mut w, ",null"))
562+
None => write!(&mut w, ",null").unwrap()
526563
}
527564
match item.search_type {
528-
Some(ref t) => try!(write!(&mut w, ",{}", t)),
529-
None => try!(write!(&mut w, ",null"))
565+
Some(ref t) => write!(&mut w, ",{}", t).unwrap(),
566+
None => write!(&mut w, ",null").unwrap()
530567
}
531-
try!(write!(&mut w, "]"));
568+
write!(&mut w, "]").unwrap();
532569
}
533570

534-
try!(write!(&mut w, r#"],"paths":["#));
571+
write!(&mut w, r#"],"paths":["#).unwrap();
535572

536573
for (i, &did) in pathid_to_nodeid.iter().enumerate() {
537574
let &(ref fqp, short) = cache.paths.get(&did).unwrap();
538575
if i > 0 {
539-
try!(write!(&mut w, ","));
576+
write!(&mut w, ",").unwrap();
540577
}
541-
try!(write!(&mut w, r#"[{},"{}"]"#,
542-
short as usize, *fqp.last().unwrap()));
578+
write!(&mut w, r#"[{},"{}"]"#,
579+
short as usize, *fqp.last().unwrap()).unwrap();
543580
}
544581

545-
try!(write!(&mut w, "]}};"));
582+
write!(&mut w, "]}};").unwrap();
546583

547-
Ok(String::from_utf8(w.into_inner()).unwrap())
584+
String::from_utf8(w.into_inner()).unwrap()
548585
}
549586

550587
fn write_shared(cx: &Context,
551588
krate: &clean::Crate,
552589
cache: &Cache,
553-
search_index: String) -> io::Result<()> {
590+
search_index: String) -> Result<(), Error> {
554591
// Write out the shared files. Note that these are shared among all rustdoc
555592
// docs placed in the output directory, so this needs to be a synchronized
556593
// operation with respect to all other rustdocs running around.
557-
try!(mkdir(&cx.dst));
594+
try_err!(mkdir(&cx.dst), &cx.dst);
558595
let _lock = ::flock::Lock::new(&cx.dst.join(".lock"));
559596

560597
// Add all the static files. These may already exist, but we just
561598
// overwrite them anyway to make sure that they're fresh and up-to-date.
562599
try!(write(cx.dst.join("jquery.js"),
563600
include_bytes!("static/jquery-2.1.4.min.js")));
564-
try!(write(cx.dst.join("main.js"), include_bytes!("static/main.js")));
565-
try!(write(cx.dst.join("playpen.js"), include_bytes!("static/playpen.js")));
566-
try!(write(cx.dst.join("main.css"), include_bytes!("static/main.css")));
601+
try!(write(cx.dst.join("main.js"),
602+
include_bytes!("static/main.js")));
603+
try!(write(cx.dst.join("playpen.js"),
604+
include_bytes!("static/playpen.js")));
605+
try!(write(cx.dst.join("main.css"),
606+
include_bytes!("static/main.css")));
567607
try!(write(cx.dst.join("normalize.css"),
568608
include_bytes!("static/normalize.css")));
569609
try!(write(cx.dst.join("FiraSans-Regular.woff"),
@@ -615,18 +655,18 @@ fn write_shared(cx: &Context,
615655

616656
// Update the search index
617657
let dst = cx.dst.join("search-index.js");
618-
let all_indexes = try!(collect(&dst, &krate.name, "searchIndex"));
619-
let mut w = try!(File::create(&dst));
620-
try!(writeln!(&mut w, "var searchIndex = {{}};"));
621-
try!(writeln!(&mut w, "{}", search_index));
658+
let all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
659+
let mut w = try_err!(File::create(&dst), &dst);
660+
try_err!(writeln!(&mut w, "var searchIndex = {{}};"), &dst);
661+
try_err!(writeln!(&mut w, "{}", search_index), &dst);
622662
for index in &all_indexes {
623-
try!(writeln!(&mut w, "{}", *index));
663+
try_err!(writeln!(&mut w, "{}", *index), &dst);
624664
}
625-
try!(writeln!(&mut w, "initSearch(searchIndex);"));
665+
try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
626666

627667
// Update the list of all implementors for traits
628668
let dst = cx.dst.join("implementors");
629-
try!(mkdir(&dst));
669+
try_err!(mkdir(&dst), &dst);
630670
for (&did, imps) in &cache.implementors {
631671
// Private modules can leak through to this phase of rustdoc, which
632672
// could contain implementations for otherwise private types. In some
@@ -643,51 +683,53 @@ fn write_shared(cx: &Context,
643683
let mut mydst = dst.clone();
644684
for part in &remote_path[..remote_path.len() - 1] {
645685
mydst.push(part);
646-
try!(mkdir(&mydst));
686+
try_err!(mkdir(&mydst), &mydst);
647687
}
648688
mydst.push(&format!("{}.{}.js",
649689
remote_item_type.to_static_str(),
650690
remote_path[remote_path.len() - 1]));
651-
let all_implementors = try!(collect(&mydst, &krate.name,
652-
"implementors"));
691+
let all_implementors = try_err!(collect(&mydst, &krate.name,
692+
"implementors"),
693+
&mydst);
653694

654-
try!(mkdir(mydst.parent().unwrap()));
655-
let mut f = BufWriter::new(try!(File::create(&mydst)));
656-
try!(writeln!(&mut f, "(function() {{var implementors = {{}};"));
695+
try_err!(mkdir(mydst.parent().unwrap()),
696+
&mydst.parent().unwrap().to_path_buf());
697+
let mut f = BufWriter::new(try_err!(File::create(&mydst), &mydst));
698+
try_err!(writeln!(&mut f, "(function() {{var implementors = {{}};"), &mydst);
657699

658700
for implementor in &all_implementors {
659-
try!(write!(&mut f, "{}", *implementor));
701+
try_err!(write!(&mut f, "{}", *implementor), &mydst);
660702
}
661703

662-
try!(write!(&mut f, r"implementors['{}'] = [", krate.name));
704+
try_err!(write!(&mut f, r"implementors['{}'] = [", krate.name), &mydst);
663705
for imp in imps {
664706
// If the trait and implementation are in the same crate, then
665707
// there's no need to emit information about it (there's inlining
666708
// going on). If they're in different crates then the crate defining
667709
// the trait will be interested in our implementation.
668710
if imp.def_id.krate == did.krate { continue }
669-
try!(write!(&mut f, r#""{}","#, imp.impl_));
711+
try_err!(write!(&mut f, r#""{}","#, imp.impl_), &mydst);
670712
}
671-
try!(writeln!(&mut f, r"];"));
672-
try!(writeln!(&mut f, "{}", r"
713+
try_err!(writeln!(&mut f, r"];"), &mydst);
714+
try_err!(writeln!(&mut f, "{}", r"
673715
if (window.register_implementors) {
674716
window.register_implementors(implementors);
675717
} else {
676718
window.pending_implementors = implementors;
677719
}
678-
"));
679-
try!(writeln!(&mut f, r"}})()"));
720+
"), &mydst);
721+
try_err!(writeln!(&mut f, r"}})()"), &mydst);
680722
}
681723
Ok(())
682724
}
683725

684726
fn render_sources(cx: &mut Context,
685-
krate: clean::Crate) -> io::Result<clean::Crate> {
727+
krate: clean::Crate) -> Result<clean::Crate, Error> {
686728
info!("emitting source files");
687729
let dst = cx.dst.join("src");
688-
try!(mkdir(&dst));
730+
try_err!(mkdir(&dst), &dst);
689731
let dst = dst.join(&krate.name);
690-
try!(mkdir(&dst));
732+
try_err!(mkdir(&dst), &dst);
691733
let mut folder = SourceCollector {
692734
dst: dst,
693735
seen: HashSet::new(),
@@ -700,8 +742,8 @@ fn render_sources(cx: &mut Context,
700742

701743
/// Writes the entire contents of a string to a destination, not attempting to
702744
/// catch any errors.
703-
fn write(dst: PathBuf, contents: &[u8]) -> io::Result<()> {
704-
try!(File::create(&dst)).write_all(contents)
745+
fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> {
746+
Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst))
705747
}
706748

707749
/// Makes a directory on the filesystem, failing the thread if an error occurs and
@@ -850,7 +892,6 @@ impl<'a> SourceCollector<'a> {
850892
fname.push(".html");
851893
cur.push(&fname[..]);
852894
let mut w = BufWriter::new(try!(File::create(&cur)));
853-
854895
let title = format!("{} -- source", cur.file_name().unwrap()
855896
.to_string_lossy());
856897
let desc = format!("Source to the Rust file `{}`.", filename);
@@ -1167,7 +1208,7 @@ impl Context {
11671208
///
11681209
/// This currently isn't parallelized, but it'd be pretty easy to add
11691210
/// parallelization to this function.
1170-
fn krate(self, mut krate: clean::Crate) -> io::Result<()> {
1211+
fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
11711212
let mut item = match krate.module.take() {
11721213
Some(i) => i,
11731214
None => return Ok(())
@@ -1193,7 +1234,7 @@ impl Context {
11931234
/// all sub-items which need to be rendered.
11941235
///
11951236
/// The rendering driver uses this closure to queue up more work.
1196-
fn item<F>(&mut self, item: clean::Item, mut f: F) -> io::Result<()> where
1237+
fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
11971238
F: FnMut(&mut Context, clean::Item),
11981239
{
11991240
fn render(w: File, cx: &Context, it: &clean::Item,
@@ -1280,9 +1321,9 @@ impl Context {
12801321
let mut item = Some(item);
12811322
self.recurse(name, |this| {
12821323
let item = item.take().unwrap();
1283-
let dst = this.dst.join("index.html");
1284-
let dst = try!(File::create(&dst));
1285-
try!(render(dst, this, &item, false));
1324+
let joint_dst = this.dst.join("index.html");
1325+
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1326+
try_err!(render(dst, this, &item, false), &joint_dst);
12861327

12871328
let m = match item.inner {
12881329
clean::ModuleItem(m) => m,
@@ -1293,9 +1334,9 @@ impl Context {
12931334
{
12941335
let items = this.build_sidebar_items(&m);
12951336
let js_dst = this.dst.join("sidebar-items.js");
1296-
let mut js_out = BufWriter::new(try!(File::create(&js_dst)));
1297-
try!(write!(&mut js_out, "initSidebarItems({});",
1298-
json::as_json(&items)));
1337+
let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
1338+
try_err!(write!(&mut js_out, "initSidebarItems({});",
1339+
json::as_json(&items)), &js_dst);
12991340
}
13001341

13011342
for item in m.items {
@@ -1308,9 +1349,11 @@ impl Context {
13081349
// Things which don't have names (like impls) don't get special
13091350
// pages dedicated to them.
13101351
_ if item.name.is_some() => {
1311-
let dst = self.dst.join(&item_path(&item));
1312-
let dst = try!(File::create(&dst));
1313-
render(dst, self, &item, true)
1352+
let joint_dst = self.dst.join(&item_path(&item));
1353+
1354+
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1355+
try_err!(render(dst, self, &item, true), &joint_dst);
1356+
Ok(())
13141357
}
13151358

13161359
_ => Ok(())

0 commit comments

Comments
 (0)