@@ -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 } ;
@@ -144,6 +145,42 @@ impl Impl {
144145 }
145146}
146147
148+ #[ derive( Debug ) ]
149+ pub struct Error {
150+ file : PathBuf ,
151+ error : io:: Error ,
152+ }
153+
154+ impl error:: Error for Error {
155+ fn description ( & self ) -> & str {
156+ self . error . description ( )
157+ }
158+ }
159+
160+ impl Display for Error {
161+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
162+ write ! ( f, "\" {}\" : {}" , self . file. display( ) , self . error)
163+ }
164+ }
165+
166+ impl Error {
167+ pub fn new ( e : io:: Error , file : & Path ) -> Error {
168+ Error {
169+ file : file. to_path_buf ( ) ,
170+ error : e,
171+ }
172+ }
173+ }
174+
175+ macro_rules! try_err {
176+ ( $e: expr, $file: expr) => ( {
177+ match $e {
178+ Ok ( e) => e,
179+ Err ( e) => return Err ( Error :: new( e, $file) ) ,
180+ }
181+ } )
182+ }
183+
147184/// This cache is used to store information about the `clean::Crate` being
148185/// rendered in order to provide more useful documentation. This contains
149186/// information like all implementors of a trait, all traits a type implements,
@@ -309,7 +346,7 @@ thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> =
309346pub fn run ( mut krate : clean:: Crate ,
310347 external_html : & ExternalHtml ,
311348 dst : PathBuf ,
312- passes : HashSet < String > ) -> io :: Result < ( ) > {
349+ passes : HashSet < String > ) -> Result < ( ) , Error > {
313350 let src_root = match krate. src . parent ( ) {
314351 Some ( p) => p. to_path_buf ( ) ,
315352 None => PathBuf :: new ( ) ,
@@ -332,7 +369,7 @@ pub fn run(mut krate: clean::Crate,
332369 issue_tracker_base_url : None ,
333370 } ;
334371
335- try !( mkdir ( & cx. dst ) ) ;
372+ try_err ! ( mkdir( & cx. dst) , & cx . dst ) ;
336373
337374 // Crawl the crate attributes looking for attributes which control how we're
338375 // going to emit HTML
@@ -434,7 +471,7 @@ pub fn run(mut krate: clean::Crate,
434471 krate = cache. fold_crate ( krate) ;
435472
436473 // Build our search index
437- let index = try! ( build_index ( & krate, & mut cache) ) ;
474+ let index = build_index ( & krate, & mut cache) ;
438475
439476 // Freeze the cache now that the index has been built. Put an Arc into TLS
440477 // for future parallelization opportunities
@@ -449,7 +486,7 @@ pub fn run(mut krate: clean::Crate,
449486 cx. krate ( krate)
450487}
451488
452- fn build_index ( krate : & clean:: Crate , cache : & mut Cache ) -> io :: Result < String > {
489+ fn build_index ( krate : & clean:: Crate , cache : & mut Cache ) -> String {
453490 // Build the search index from the collected metadata
454491 let mut nodeid_to_pathid = HashMap :: new ( ) ;
455492 let mut pathid_to_nodeid = Vec :: new ( ) ;
@@ -476,7 +513,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
476513 } ,
477514 None => { }
478515 }
479- } ;
516+ }
480517
481518 // Reduce `NodeId` in paths into smaller sequential numbers,
482519 // and prune the paths that do not appear in the index.
@@ -497,7 +534,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
497534
498535 // Collect the index into a string
499536 let mut w = io:: Cursor :: new ( Vec :: new ( ) ) ;
500- try! ( write ! ( & mut w, r#"searchIndex['{}'] = {{"items":["# , krate. name) ) ;
537+ write ! ( & mut w, r#"searchIndex['{}'] = {{"items":["# , krate. name) . unwrap ( ) ;
501538
502539 let mut lastpath = "" . to_string ( ) ;
503540 for ( i, item) in cache. search_index . iter ( ) . enumerate ( ) {
@@ -511,58 +548,61 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
511548 } ;
512549
513550 if i > 0 {
514- try! ( write ! ( & mut w, "," ) ) ;
551+ write ! ( & mut w, "," ) . unwrap ( ) ;
515552 }
516- try! ( write ! ( & mut w, r#"[{},"{}","{}",{}"# ,
517- item. ty as usize , item. name, path,
518- item. desc. to_json( ) . to_string( ) ) ) ;
553+ write ! ( & mut w, r#"[{},"{}","{}",{}"# ,
554+ item. ty as usize , item. name, path,
555+ item. desc. to_json( ) . to_string( ) ) . unwrap ( ) ;
519556 match item. parent {
520557 Some ( nodeid) => {
521558 let pathid = * nodeid_to_pathid. get ( & nodeid) . unwrap ( ) ;
522- try! ( write ! ( & mut w, ",{}" , pathid) ) ;
559+ write ! ( & mut w, ",{}" , pathid) . unwrap ( ) ;
523560 }
524- None => try! ( write ! ( & mut w, ",null" ) )
561+ None => write ! ( & mut w, ",null" ) . unwrap ( )
525562 }
526563 match item. search_type {
527- Some ( ref t) => try! ( write ! ( & mut w, ",{}" , t) ) ,
528- None => try! ( write ! ( & mut w, ",null" ) )
564+ Some ( ref t) => write ! ( & mut w, ",{}" , t) . unwrap ( ) ,
565+ None => write ! ( & mut w, ",null" ) . unwrap ( )
529566 }
530- try! ( write ! ( & mut w, "]" ) ) ;
567+ write ! ( & mut w, "]" ) . unwrap ( ) ;
531568 }
532569
533- try! ( write ! ( & mut w, r#"],"paths":["# ) ) ;
570+ write ! ( & mut w, r#"],"paths":["# ) . unwrap ( ) ;
534571
535572 for ( i, & did) in pathid_to_nodeid. iter ( ) . enumerate ( ) {
536573 let & ( ref fqp, short) = cache. paths . get ( & did) . unwrap ( ) ;
537574 if i > 0 {
538- try! ( write ! ( & mut w, "," ) ) ;
575+ write ! ( & mut w, "," ) . unwrap ( ) ;
539576 }
540- try! ( write ! ( & mut w, r#"[{},"{}"]"# ,
541- short as usize , * fqp. last( ) . unwrap( ) ) ) ;
577+ write ! ( & mut w, r#"[{},"{}"]"# ,
578+ short as usize , * fqp. last( ) . unwrap( ) ) . unwrap ( ) ;
542579 }
543580
544- try! ( write ! ( & mut w, "]}};" ) ) ;
581+ write ! ( & mut w, "]}};" ) . unwrap ( ) ;
545582
546- Ok ( String :: from_utf8 ( w. into_inner ( ) ) . unwrap ( ) )
583+ String :: from_utf8 ( w. into_inner ( ) ) . unwrap ( )
547584}
548585
549586fn write_shared ( cx : & Context ,
550587 krate : & clean:: Crate ,
551588 cache : & Cache ,
552- search_index : String ) -> io :: Result < ( ) > {
589+ search_index : String ) -> Result < ( ) , Error > {
553590 // Write out the shared files. Note that these are shared among all rustdoc
554591 // docs placed in the output directory, so this needs to be a synchronized
555592 // operation with respect to all other rustdocs running around.
556- try !( mkdir ( & cx. dst ) ) ;
593+ try_err ! ( mkdir( & cx. dst) , & cx . dst ) ;
557594 let _lock = :: flock:: Lock :: new ( & cx. dst . join ( ".lock" ) ) ;
558595
559596 // Add all the static files. These may already exist, but we just
560597 // overwrite them anyway to make sure that they're fresh and up-to-date.
561598 try!( write ( cx. dst . join ( "jquery.js" ) ,
562599 include_bytes ! ( "static/jquery-2.1.4.min.js" ) ) ) ;
563- try!( write ( cx. dst . join ( "main.js" ) , include_bytes ! ( "static/main.js" ) ) ) ;
564- try!( write ( cx. dst . join ( "playpen.js" ) , include_bytes ! ( "static/playpen.js" ) ) ) ;
565- try!( write ( cx. dst . join ( "main.css" ) , include_bytes ! ( "static/main.css" ) ) ) ;
600+ try!( write ( cx. dst . join ( "main.js" ) ,
601+ include_bytes ! ( "static/main.js" ) ) ) ;
602+ try!( write ( cx. dst . join ( "playpen.js" ) ,
603+ include_bytes ! ( "static/playpen.js" ) ) ) ;
604+ try!( write ( cx. dst . join ( "main.css" ) ,
605+ include_bytes ! ( "static/main.css" ) ) ) ;
566606 try!( write ( cx. dst . join ( "normalize.css" ) ,
567607 include_bytes ! ( "static/normalize.css" ) ) ) ;
568608 try!( write ( cx. dst . join ( "FiraSans-Regular.woff" ) ,
@@ -614,18 +654,18 @@ fn write_shared(cx: &Context,
614654
615655 // Update the search index
616656 let dst = cx. dst . join ( "search-index.js" ) ;
617- let all_indexes = try !( collect ( & dst, & krate. name , "searchIndex" ) ) ;
618- let mut w = try !( File :: create ( & dst) ) ;
619- try !( writeln ! ( & mut w, "var searchIndex = {{}};" ) ) ;
620- try !( writeln ! ( & mut w, "{}" , search_index) ) ;
657+ let all_indexes = try_err ! ( collect( & dst, & krate. name, "searchIndex" ) , & dst ) ;
658+ let mut w = try_err ! ( File :: create( & dst) , & dst ) ;
659+ try_err ! ( writeln!( & mut w, "var searchIndex = {{}};" ) , & dst ) ;
660+ try_err ! ( writeln!( & mut w, "{}" , search_index) , & dst ) ;
621661 for index in & all_indexes {
622- try !( writeln ! ( & mut w, "{}" , * index) ) ;
662+ try_err ! ( writeln!( & mut w, "{}" , * index) , & dst ) ;
623663 }
624- try !( writeln ! ( & mut w, "initSearch(searchIndex);" ) ) ;
664+ try_err ! ( writeln!( & mut w, "initSearch(searchIndex);" ) , & dst ) ;
625665
626666 // Update the list of all implementors for traits
627667 let dst = cx. dst . join ( "implementors" ) ;
628- try !( mkdir ( & dst) ) ;
668+ try_err ! ( mkdir( & dst) , & dst ) ;
629669 for ( & did, imps) in & cache. implementors {
630670 // Private modules can leak through to this phase of rustdoc, which
631671 // could contain implementations for otherwise private types. In some
@@ -642,51 +682,53 @@ fn write_shared(cx: &Context,
642682 let mut mydst = dst. clone ( ) ;
643683 for part in & remote_path[ ..remote_path. len ( ) - 1 ] {
644684 mydst. push ( part) ;
645- try !( mkdir ( & mydst) ) ;
685+ try_err ! ( mkdir( & mydst) , & mydst ) ;
646686 }
647687 mydst. push ( & format ! ( "{}.{}.js" ,
648688 remote_item_type. to_static_str( ) ,
649689 remote_path[ remote_path. len( ) - 1 ] ) ) ;
650- let all_implementors = try!( collect ( & mydst, & krate. name ,
651- "implementors" ) ) ;
690+ let all_implementors = try_err ! ( collect( & mydst, & krate. name,
691+ "implementors" ) ,
692+ & mydst) ;
652693
653- try!( mkdir ( mydst. parent ( ) . unwrap ( ) ) ) ;
654- let mut f = BufWriter :: new ( try!( File :: create ( & mydst) ) ) ;
655- try!( writeln ! ( & mut f, "(function() {{var implementors = {{}};" ) ) ;
694+ try_err ! ( mkdir( mydst. parent( ) . unwrap( ) ) ,
695+ & mydst. parent( ) . unwrap( ) . to_path_buf( ) ) ;
696+ let mut f = BufWriter :: new ( try_err ! ( File :: create( & mydst) , & mydst) ) ;
697+ try_err ! ( writeln!( & mut f, "(function() {{var implementors = {{}};" ) , & mydst) ;
656698
657699 for implementor in & all_implementors {
658- try !( write ! ( & mut f, "{}" , * implementor) ) ;
700+ try_err ! ( write!( & mut f, "{}" , * implementor) , & mydst ) ;
659701 }
660702
661- try !( write ! ( & mut f, r"implementors['{}'] = [" , krate. name) ) ;
703+ try_err ! ( write!( & mut f, r"implementors['{}'] = [" , krate. name) , & mydst ) ;
662704 for imp in imps {
663705 // If the trait and implementation are in the same crate, then
664706 // there's no need to emit information about it (there's inlining
665707 // going on). If they're in different crates then the crate defining
666708 // the trait will be interested in our implementation.
667709 if imp. def_id . krate == did. krate { continue }
668- try !( write ! ( & mut f, r#""{}","# , imp. impl_) ) ;
710+ try_err ! ( write!( & mut f, r#""{}","# , imp. impl_) , & mydst ) ;
669711 }
670- try !( writeln ! ( & mut f, r"];" ) ) ;
671- try !( writeln ! ( & mut f, "{}" , r"
712+ try_err ! ( writeln!( & mut f, r"];" ) , & mydst ) ;
713+ try_err ! ( writeln!( & mut f, "{}" , r"
672714 if (window.register_implementors) {
673715 window.register_implementors(implementors);
674716 } else {
675717 window.pending_implementors = implementors;
676718 }
677- " ) ) ;
678- try !( writeln ! ( & mut f, r"}})()" ) ) ;
719+ " ) , & mydst ) ;
720+ try_err ! ( writeln!( & mut f, r"}})()" ) , & mydst ) ;
679721 }
680722 Ok ( ( ) )
681723}
682724
683725fn render_sources ( cx : & mut Context ,
684- krate : clean:: Crate ) -> io :: Result < clean:: Crate > {
726+ krate : clean:: Crate ) -> Result < clean:: Crate , Error > {
685727 info ! ( "emitting source files" ) ;
686728 let dst = cx. dst . join ( "src" ) ;
687- try !( mkdir ( & dst) ) ;
729+ try_err ! ( mkdir( & dst) , & dst ) ;
688730 let dst = dst. join ( & krate. name ) ;
689- try !( mkdir ( & dst) ) ;
731+ try_err ! ( mkdir( & dst) , & dst ) ;
690732 let mut folder = SourceCollector {
691733 dst : dst,
692734 seen : HashSet :: new ( ) ,
@@ -699,8 +741,8 @@ fn render_sources(cx: &mut Context,
699741
700742/// Writes the entire contents of a string to a destination, not attempting to
701743/// catch any errors.
702- fn write ( dst : PathBuf , contents : & [ u8 ] ) -> io :: Result < ( ) > {
703- try! ( File :: create ( & dst) ) . write_all ( contents)
744+ fn write ( dst : PathBuf , contents : & [ u8 ] ) -> Result < ( ) , Error > {
745+ Ok ( try_err ! ( try_err! ( File :: create( & dst) , & dst ) . write_all( contents) , & dst ) )
704746}
705747
706748/// Makes a directory on the filesystem, failing the thread if an error occurs and
@@ -849,7 +891,6 @@ impl<'a> SourceCollector<'a> {
849891 fname. push ( ".html" ) ;
850892 cur. push ( & fname[ ..] ) ;
851893 let mut w = BufWriter :: new ( try!( File :: create ( & cur) ) ) ;
852-
853894 let title = format ! ( "{} -- source" , cur. file_name( ) . unwrap( )
854895 . to_string_lossy( ) ) ;
855896 let desc = format ! ( "Source to the Rust file `{}`." , filename) ;
@@ -1166,7 +1207,7 @@ impl Context {
11661207 ///
11671208 /// This currently isn't parallelized, but it'd be pretty easy to add
11681209 /// parallelization to this function.
1169- fn krate ( self , mut krate : clean:: Crate ) -> io :: Result < ( ) > {
1210+ fn krate ( self , mut krate : clean:: Crate ) -> Result < ( ) , Error > {
11701211 let mut item = match krate. module . take ( ) {
11711212 Some ( i) => i,
11721213 None => return Ok ( ( ) )
@@ -1192,7 +1233,7 @@ impl Context {
11921233 /// all sub-items which need to be rendered.
11931234 ///
11941235 /// The rendering driver uses this closure to queue up more work.
1195- fn item < F > ( & mut self , item : clean:: Item , mut f : F ) -> io :: Result < ( ) > where
1236+ fn item < F > ( & mut self , item : clean:: Item , mut f : F ) -> Result < ( ) , Error > where
11961237 F : FnMut ( & mut Context , clean:: Item ) ,
11971238 {
11981239 fn render ( w : File , cx : & Context , it : & clean:: Item ,
@@ -1279,9 +1320,9 @@ impl Context {
12791320 let mut item = Some ( item) ;
12801321 self . recurse ( name, |this| {
12811322 let item = item. take ( ) . unwrap ( ) ;
1282- let dst = this. dst . join ( "index.html" ) ;
1283- let dst = try !( File :: create ( & dst ) ) ;
1284- try !( render ( dst, this, & item, false ) ) ;
1323+ let joint_dst = this. dst . join ( "index.html" ) ;
1324+ let dst = try_err ! ( File :: create( & joint_dst ) , & joint_dst ) ;
1325+ try_err ! ( render( dst, this, & item, false ) , & joint_dst ) ;
12851326
12861327 let m = match item. inner {
12871328 clean:: ModuleItem ( m) => m,
@@ -1292,9 +1333,9 @@ impl Context {
12921333 {
12931334 let items = this. build_sidebar_items ( & m) ;
12941335 let js_dst = this. dst . join ( "sidebar-items.js" ) ;
1295- let mut js_out = BufWriter :: new ( try !( File :: create ( & js_dst) ) ) ;
1296- try !( write ! ( & mut js_out, "initSidebarItems({});" ,
1297- json:: as_json( & items) ) ) ;
1336+ let mut js_out = BufWriter :: new ( try_err ! ( File :: create( & js_dst) , & js_dst ) ) ;
1337+ try_err ! ( write!( & mut js_out, "initSidebarItems({});" ,
1338+ json:: as_json( & items) ) , & js_dst ) ;
12981339 }
12991340
13001341 for item in m. items {
@@ -1307,9 +1348,11 @@ impl Context {
13071348 // Things which don't have names (like impls) don't get special
13081349 // pages dedicated to them.
13091350 _ if item. name . is_some ( ) => {
1310- let dst = self . dst . join ( & item_path ( & item) ) ;
1311- let dst = try!( File :: create ( & dst) ) ;
1312- render ( dst, self , & item, true )
1351+ let joint_dst = self . dst . join ( & item_path ( & item) ) ;
1352+
1353+ let dst = try_err ! ( File :: create( & joint_dst) , & joint_dst) ;
1354+ try_err ! ( render( dst, self , & item, true ) , & joint_dst) ;
1355+ Ok ( ( ) )
13131356 }
13141357
13151358 _ => Ok ( ( ) )
0 commit comments