@@ -39,7 +39,8 @@ use std::cell::RefCell;
3939use std:: cmp:: Ordering ;
4040use std:: collections:: { BTreeMap , HashMap , HashSet } ;
4141use std:: default:: Default ;
42- use std:: fmt;
42+ use std:: error;
43+ use std:: fmt:: { self , Display , Formatter } ;
4344use std:: fs:: { self , File } ;
4445use std:: io:: prelude:: * ;
4546use 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>> =
310347pub 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
550587fn 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
684726fn 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