@@ -287,6 +287,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
287287 format ! ( "{:x}" , hash. finish( ) )
288288}
289289
290+ #[ derive( Copy , Clone ) ]
290291struct TestCx < ' test > {
291292 config : & ' test Config ,
292293 props : & ' test TestProps ,
@@ -2208,7 +2209,12 @@ impl<'test> TestCx<'test> {
22082209
22092210 fn fatal_proc_rec ( & self , err : & str , proc_res : & ProcRes ) -> ! {
22102211 self . error ( err) ;
2211- proc_res. fatal ( None ) ;
2212+ proc_res. fatal ( None , || ( ) ) ;
2213+ }
2214+
2215+ fn fatal_proc_rec_with_ctx ( & self , err : & str , proc_res : & ProcRes , ctx : impl FnOnce ( Self ) ) -> ! {
2216+ self . error ( err) ;
2217+ proc_res. fatal ( None , || ctx ( * self ) ) ;
22122218 }
22132219
22142220 // codegen tests (using FileCheck)
@@ -2325,15 +2331,72 @@ impl<'test> TestCx<'test> {
23252331 let res = self . cmd2procres (
23262332 Command :: new ( & self . config . docck_python )
23272333 . arg ( root. join ( "src/etc/htmldocck.py" ) )
2328- . arg ( out_dir)
2334+ . arg ( & out_dir)
23292335 . arg ( & self . testpaths . file ) ,
23302336 ) ;
23312337 if !res. status . success ( ) {
2332- self . fatal_proc_rec ( "htmldocck failed!" , & res) ;
2338+ self . fatal_proc_rec_with_ctx ( "htmldocck failed!" , & res, |mut this| {
2339+ this. compare_to_default_rustdoc ( & out_dir)
2340+ } ) ;
23332341 }
23342342 }
23352343 }
23362344
2345+ fn compare_to_default_rustdoc ( & mut self , out_dir : & Path ) {
2346+ println ! ( "info: generating a diff against nightly rustdoc" ) ;
2347+
2348+ let suffix =
2349+ self . safe_revision ( ) . map_or ( "nightly" . into ( ) , |path| path. to_owned ( ) + "-nightly" ) ;
2350+ let compare_dir = output_base_dir ( self . config , self . testpaths , Some ( & suffix) ) ;
2351+ let _ = fs:: remove_dir_all ( & compare_dir) ;
2352+ create_dir_all ( & compare_dir) . unwrap ( ) ;
2353+
2354+ // We need to create a new struct for the lifetimes on `config` to work.
2355+ let new_rustdoc = TestCx {
2356+ config : & Config {
2357+ // FIXME: use beta or a user-specified rustdoc instead of hardcoding
2358+ // the default toolchain
2359+ rustdoc_path : Some ( "rustdoc" . into ( ) ) ,
2360+ ..self . config . clone ( )
2361+ } ,
2362+ ..* self
2363+ } ;
2364+ let proc_res = new_rustdoc. document ( & compare_dir) ;
2365+ if !proc_res. status . success ( ) {
2366+ proc_res. fatal ( Some ( "failed to run nightly rustdoc" ) , || ( ) ) ;
2367+ }
2368+
2369+ // NOTE: this is fine since compiletest never runs out-of-tree
2370+ let tidy = concat ! ( env!( "CARGO_MANIFEST_DIR" ) , "/tidy-rustdoc.sh" ) ;
2371+ // FIXME: this overwrites `out_dir` in place, maybe we should make a copy?
2372+ let status = Command :: new ( tidy)
2373+ . arg ( out_dir)
2374+ . spawn ( )
2375+ . expect ( "tidy-rustdoc not found" )
2376+ . wait ( )
2377+ . unwrap ( ) ;
2378+ if !status. success ( ) {
2379+ self . fatal ( "failed to run tidy - is installed?" ) ;
2380+ }
2381+ let status = Command :: new ( tidy) . arg ( & compare_dir) . spawn ( ) . unwrap ( ) . wait ( ) . unwrap ( ) ;
2382+ if !status. success ( ) {
2383+ self . fatal ( "failed to run tidy" ) ;
2384+ }
2385+
2386+ let diff_pid = Command :: new ( "diff" )
2387+ . args ( & [ "-u" , "-r" ] )
2388+ . args ( & [ out_dir, & compare_dir] )
2389+ . stdout ( Stdio :: piped ( ) )
2390+ . spawn ( )
2391+ . expect ( "failed to run `diff`" ) ;
2392+ Command :: new ( "delta" )
2393+ . stdin ( diff_pid. stdout . unwrap ( ) )
2394+ . spawn ( )
2395+ . expect ( "delta not found" )
2396+ . wait ( )
2397+ . unwrap ( ) ;
2398+ }
2399+
23372400 fn get_lines < P : AsRef < Path > > (
23382401 & self ,
23392402 path : & P ,
@@ -3590,7 +3653,7 @@ pub struct ProcRes {
35903653}
35913654
35923655impl ProcRes {
3593- pub fn fatal ( & self , err : Option < & str > ) -> ! {
3656+ pub fn fatal ( & self , err : Option < & str > , ctx : impl FnOnce ( ) ) -> ! {
35943657 if let Some ( e) = err {
35953658 println ! ( "\n error: {}" , e) ;
35963659 }
@@ -3612,6 +3675,7 @@ impl ProcRes {
36123675 json:: extract_rendered( & self . stdout) ,
36133676 json:: extract_rendered( & self . stderr) ,
36143677 ) ;
3678+ ctx ( ) ;
36153679 // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from
36163680 // compiletest, which is unnecessary noise.
36173681 std:: panic:: resume_unwind ( Box :: new ( ( ) ) ) ;
0 commit comments