@@ -407,7 +407,7 @@ pub(crate) fn run_tests(
407407 // We failed to compile all compatible tests as one so we push them into the
408408 // `standalone_tests` doctests.
409409 debug ! ( "Failed to compile compatible doctests for edition {} all at once" , edition) ;
410- for ( doctest, scraped_test) in doctests {
410+ for ( pos , ( doctest, scraped_test) ) in doctests. into_iter ( ) . enumerate ( ) {
411411 doctest. generate_unique_doctest (
412412 & scraped_test. text ,
413413 scraped_test. langstr . test_harness ,
@@ -420,6 +420,7 @@ pub(crate) fn run_tests(
420420 opts. clone ( ) ,
421421 Arc :: clone ( rustdoc_options) ,
422422 unused_extern_reports. clone ( ) ,
423+ pos,
423424 ) ) ;
424425 }
425426 }
@@ -549,11 +550,21 @@ pub(crate) struct RunnableDocTest {
549550}
550551
551552impl RunnableDocTest {
552- fn path_for_merged_doctest_bundle ( & self ) -> PathBuf {
553- self . test_opts . outdir . path ( ) . join ( format ! ( "doctest_bundle_{}.rs" , self . edition) )
553+ fn path_for_merged_doctest_bundle ( & self , id : Option < usize > ) -> PathBuf {
554+ let name = if let Some ( id) = id {
555+ format ! ( "doctest_bundle_id_{id}.rs" )
556+ } else {
557+ format ! ( "doctest_bundle_{}.rs" , self . edition)
558+ } ;
559+ self . test_opts . outdir . path ( ) . join ( name)
554560 }
555- fn path_for_merged_doctest_runner ( & self ) -> PathBuf {
556- self . test_opts . outdir . path ( ) . join ( format ! ( "doctest_runner_{}.rs" , self . edition) )
561+ fn path_for_merged_doctest_runner ( & self , id : Option < usize > ) -> PathBuf {
562+ let name = if let Some ( id) = id {
563+ format ! ( "doctest_runner_id_{id}.rs" )
564+ } else {
565+ format ! ( "doctest_runner_{}.rs" , self . edition)
566+ } ;
567+ self . test_opts . outdir . path ( ) . join ( name)
557568 }
558569 fn is_multiple_tests ( & self ) -> bool {
559570 self . merged_test_code . is_some ( )
@@ -569,13 +580,14 @@ fn compile_merged_doctest_and_caller_binary(
569580 compiler_args : Vec < String > ,
570581 test_code : & str ,
571582 instant : Instant ,
583+ id : Option < usize > ,
572584) -> Result < process:: Output , ( Duration , Result < ( ) , RustdocResult > ) > {
573585 // compile-fail tests never get merged, so this should always pass
574586 let status = child. wait ( ) . expect ( "Failed to wait" ) ;
575587
576588 // the actual test runner is a separate component, built with nightly-only features;
577589 // build it now
578- let runner_input_file = doctest. path_for_merged_doctest_runner ( ) ;
590+ let runner_input_file = doctest. path_for_merged_doctest_runner ( id ) ;
579591
580592 let mut runner_compiler =
581593 wrapped_rustc_command ( & rustdoc_options. test_builder_wrappers , rustc_binary) ;
@@ -584,10 +596,14 @@ fn compile_merged_doctest_and_caller_binary(
584596 runner_compiler. env ( "RUSTC_BOOTSTRAP" , "1" ) ;
585597 runner_compiler. args ( compiler_args) ;
586598 runner_compiler. args ( [ "--crate-type=bin" , "-o" ] ) . arg ( output_file) ;
587- let mut extern_path = std:: ffi:: OsString :: from ( format ! (
588- "--extern=doctest_bundle_{edition}=" ,
589- edition = doctest. edition
590- ) ) ;
599+ let mut extern_path = if let Some ( id) = id {
600+ std:: ffi:: OsString :: from ( format ! ( "--extern=doctest_bundle_id_{id}=" ) )
601+ } else {
602+ std:: ffi:: OsString :: from ( format ! (
603+ "--extern=doctest_bundle_{edition}=" ,
604+ edition = doctest. edition
605+ ) )
606+ } ;
591607
592608 // Deduplicate passed -L directory paths, since usually all dependencies will be in the
593609 // same directory (e.g. target/debug/deps from Cargo).
@@ -606,11 +622,12 @@ fn compile_merged_doctest_and_caller_binary(
606622 }
607623 }
608624 }
609- let output_bundle_file = doctest
610- . test_opts
611- . outdir
612- . path ( )
613- . join ( format ! ( "libdoctest_bundle_{edition}.rlib" , edition = doctest. edition) ) ;
625+ let filename = if let Some ( id) = id {
626+ format ! ( "libdoctest_bundle_id_{id}.rlib" )
627+ } else {
628+ format ! ( "libdoctest_bundle_{edition}.rlib" , edition = doctest. edition)
629+ } ;
630+ let output_bundle_file = doctest. test_opts . outdir . path ( ) . join ( filename) ;
614631 extern_path. push ( & output_bundle_file) ;
615632 runner_compiler. arg ( extern_path) ;
616633 runner_compiler. arg ( & runner_input_file) ;
@@ -648,6 +665,7 @@ fn run_test(
648665 rustdoc_options : & RustdocOptions ,
649666 supports_color : bool ,
650667 report_unused_externs : impl Fn ( UnusedExterns ) ,
668+ doctest_id : usize ,
651669) -> ( Duration , Result < ( ) , RustdocResult > ) {
652670 let langstr = & doctest. langstr ;
653671 // Make sure we emit well-formed executable names for our target.
@@ -728,12 +746,19 @@ fn run_test(
728746
729747 compiler. args ( & compiler_args) ;
730748
749+ compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , & doctest. test_opts . path ) ;
750+ compiler. env (
751+ "UNSTABLE_RUSTDOC_TEST_LINE" ,
752+ format ! ( "{}" , doctest. line as isize - doctest. full_test_line_offset as isize ) ,
753+ ) ;
731754 // If this is a merged doctest, we need to write it into a file instead of using stdin
732755 // because if the size of the merged doctests is too big, it'll simply break stdin.
733- if doctest. is_multiple_tests ( ) {
756+ if doctest. is_multiple_tests ( ) || ( !langstr . compile_fail && langstr . should_panic ) {
734757 // It makes the compilation failure much faster if it is for a combined doctest.
735758 compiler. arg ( "--error-format=short" ) ;
736- let input_file = doctest. path_for_merged_doctest_bundle ( ) ;
759+ let input_file = doctest. path_for_merged_doctest_bundle (
760+ if !langstr. compile_fail && langstr. should_panic { Some ( doctest_id) } else { None } ,
761+ ) ;
737762 if std:: fs:: write ( & input_file, & doctest. full_test_code ) . is_err ( ) {
738763 // If we cannot write this file for any reason, we leave. All combined tests will be
739764 // tested as standalone tests.
@@ -752,11 +777,6 @@ fn run_test(
752777 . arg ( input_file) ;
753778 } else {
754779 compiler. arg ( "--crate-type=bin" ) . arg ( "-o" ) . arg ( & output_file) ;
755- compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , & doctest. test_opts . path ) ;
756- compiler. env (
757- "UNSTABLE_RUSTDOC_TEST_LINE" ,
758- format ! ( "{}" , doctest. line as isize - doctest. full_test_line_offset as isize ) ,
759- ) ;
760780 compiler. arg ( "-" ) ;
761781 compiler. stdin ( Stdio :: piped ( ) ) ;
762782 compiler. stderr ( Stdio :: piped ( ) ) ;
@@ -775,6 +795,37 @@ fn run_test(
775795 compiler_args,
776796 merged_test_code,
777797 instant,
798+ None ,
799+ ) {
800+ Ok ( out) => out,
801+ Err ( err) => return err,
802+ }
803+ } else if !langstr. compile_fail && langstr. should_panic {
804+ match compile_merged_doctest_and_caller_binary (
805+ child,
806+ & doctest,
807+ rustdoc_options,
808+ rustc_binary,
809+ & output_file,
810+ compiler_args,
811+ & format ! (
812+ "\
813+ #![feature(test)]
814+ extern crate test;
815+
816+ use std::process::{{ExitCode, Termination}};
817+
818+ fn main() -> ExitCode {{
819+ if test::cannot_handle_should_panic() {{
820+ ExitCode::SUCCESS
821+ }} else {{
822+ extern crate doctest_bundle_id_{doctest_id} as doctest_bundle;
823+ doctest_bundle::main().report()
824+ }}
825+ }}"
826+ ) ,
827+ instant,
828+ Some ( doctest_id) ,
778829 ) {
779830 Ok ( out) => out,
780831 Err ( err) => return err,
@@ -1091,6 +1142,7 @@ impl CreateRunnableDocTests {
10911142 self . opts . clone ( ) ,
10921143 Arc :: clone ( & self . rustdoc_options ) ,
10931144 self . unused_extern_reports . clone ( ) ,
1145+ self . standalone_tests . len ( ) ,
10941146 )
10951147 }
10961148}
@@ -1101,6 +1153,7 @@ fn generate_test_desc_and_fn(
11011153 opts : GlobalTestOptions ,
11021154 rustdoc_options : Arc < RustdocOptions > ,
11031155 unused_externs : Arc < Mutex < Vec < UnusedExterns > > > ,
1156+ doctest_id : usize ,
11041157) -> test:: TestDescAndFn {
11051158 let target_str = rustdoc_options. target . to_string ( ) ;
11061159 let rustdoc_test_options =
@@ -1135,6 +1188,7 @@ fn generate_test_desc_and_fn(
11351188 scraped_test,
11361189 rustdoc_options,
11371190 unused_externs,
1191+ doctest_id,
11381192 )
11391193 } ) ) ,
11401194 }
@@ -1147,6 +1201,7 @@ fn doctest_run_fn(
11471201 scraped_test : ScrapedDocTest ,
11481202 rustdoc_options : Arc < RustdocOptions > ,
11491203 unused_externs : Arc < Mutex < Vec < UnusedExterns > > > ,
1204+ doctest_id : usize ,
11501205) -> Result < ( ) , String > {
11511206 #[ cfg( not( bootstrap) ) ]
11521207 if scraped_test. langstr . should_panic && test:: cannot_handle_should_panic ( ) {
@@ -1172,8 +1227,13 @@ fn doctest_run_fn(
11721227 no_run : scraped_test. no_run ( & rustdoc_options) ,
11731228 merged_test_code : None ,
11741229 } ;
1175- let ( _, res) =
1176- run_test ( runnable_test, & rustdoc_options, doctest. supports_color , report_unused_externs) ;
1230+ let ( _, res) = run_test (
1231+ runnable_test,
1232+ & rustdoc_options,
1233+ doctest. supports_color ,
1234+ report_unused_externs,
1235+ doctest_id,
1236+ ) ;
11771237
11781238 if let Err ( err) = res {
11791239 eprint ! ( "{err}" ) ;
0 commit comments