@@ -369,57 +369,59 @@ fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Com
369
369
command
370
370
}
371
371
372
+ struct RunnableDoctest {
373
+ full_test_code : String ,
374
+ full_test_line_offset : usize ,
375
+ test_opts : IndividualTestOptions ,
376
+ global_opts : GlobalTestOptions ,
377
+ scraped_test : ScrapedDoctest ,
378
+ }
379
+
372
380
fn run_test (
373
- test : & str ,
374
- line : usize ,
381
+ doctest : RunnableDoctest ,
375
382
rustdoc_options : & RustdocOptions ,
376
- test_options : IndividualTestOptions ,
377
- mut lang_string : LangString ,
378
- no_run : bool ,
379
- opts : & GlobalTestOptions ,
380
- edition : Edition ,
383
+ supports_color : bool ,
381
384
report_unused_externs : impl Fn ( UnusedExterns ) ,
382
385
) -> Result < ( ) , TestFailure > {
383
- let ( test, line_offset, supports_color) = make_test (
384
- test,
385
- Some ( & opts. crate_name ) ,
386
- lang_string. test_harness ,
387
- opts,
388
- edition,
389
- Some ( & test_options. test_id ) ,
390
- ) ;
391
-
386
+ let scraped_test = & doctest. scraped_test ;
387
+ let langstr = & scraped_test. langstr ;
392
388
// Make sure we emit well-formed executable names for our target.
393
389
let rust_out = add_exe_suffix ( "rust_out" . to_owned ( ) , & rustdoc_options. target ) ;
394
- let output_file = test_options . outdir . path ( ) . join ( rust_out) ;
390
+ let output_file = doctest . test_opts . outdir . path ( ) . join ( rust_out) ;
395
391
396
392
let rustc_binary = rustdoc_options
397
393
. test_builder
398
394
. as_deref ( )
399
395
. unwrap_or_else ( || rustc_interface:: util:: rustc_path ( ) . expect ( "found rustc" ) ) ;
400
396
let mut compiler = wrapped_rustc_command ( & rustdoc_options. test_builder_wrappers , rustc_binary) ;
401
397
402
- compiler. arg ( & format ! ( "@{}" , opts . args_file. display( ) ) ) ;
398
+ compiler. arg ( & format ! ( "@{}" , doctest . global_opts . args_file. display( ) ) ) ;
403
399
404
400
if let Some ( sysroot) = & rustdoc_options. maybe_sysroot {
405
401
compiler. arg ( format ! ( "--sysroot={}" , sysroot. display( ) ) ) ;
406
402
}
407
403
408
- compiler. arg ( "--edition" ) . arg ( & edition. to_string ( ) ) ;
409
- compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , & test_options. path ) ;
410
- compiler. env ( "UNSTABLE_RUSTDOC_TEST_LINE" , format ! ( "{}" , line as isize - line_offset as isize ) ) ;
404
+ compiler. arg ( "--edition" ) . arg ( & scraped_test. edition ( rustdoc_options) . to_string ( ) ) ;
405
+ compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , & doctest. test_opts . path ) ;
406
+ compiler. env (
407
+ "UNSTABLE_RUSTDOC_TEST_LINE" ,
408
+ format ! ( "{}" , scraped_test. line as isize - doctest. full_test_line_offset as isize ) ,
409
+ ) ;
411
410
compiler. arg ( "-o" ) . arg ( & output_file) ;
412
- if lang_string . test_harness {
411
+ if langstr . test_harness {
413
412
compiler. arg ( "--test" ) ;
414
413
}
415
- if rustdoc_options. json_unused_externs . is_enabled ( ) && !lang_string . compile_fail {
414
+ if rustdoc_options. json_unused_externs . is_enabled ( ) && !langstr . compile_fail {
416
415
compiler. arg ( "--error-format=json" ) ;
417
416
compiler. arg ( "--json" ) . arg ( "unused-externs" ) ;
418
417
compiler. arg ( "-W" ) . arg ( "unused_crate_dependencies" ) ;
419
418
compiler. arg ( "-Z" ) . arg ( "unstable-options" ) ;
420
419
}
421
420
422
- if no_run && !lang_string. compile_fail && rustdoc_options. persist_doctests . is_none ( ) {
421
+ if scraped_test. no_run ( rustdoc_options)
422
+ && !langstr. compile_fail
423
+ && rustdoc_options. persist_doctests . is_none ( )
424
+ {
423
425
// FIXME: why does this code check if it *shouldn't* persist doctests
424
426
// -- shouldn't it be the negation?
425
427
compiler. arg ( "--emit=metadata" ) ;
@@ -459,7 +461,7 @@ fn run_test(
459
461
let mut child = compiler. spawn ( ) . expect ( "Failed to spawn rustc process" ) ;
460
462
{
461
463
let stdin = child. stdin . as_mut ( ) . expect ( "Failed to open stdin" ) ;
462
- stdin. write_all ( test . as_bytes ( ) ) . expect ( "could write out test sources" ) ;
464
+ stdin. write_all ( doctest . full_test_code . as_bytes ( ) ) . expect ( "could write out test sources" ) ;
463
465
}
464
466
let output = child. wait_with_output ( ) . expect ( "Failed to read stdout" ) ;
465
467
@@ -490,20 +492,26 @@ fn run_test(
490
492
}
491
493
492
494
let _bomb = Bomb ( & out) ;
493
- match ( output. status . success ( ) , lang_string . compile_fail ) {
495
+ match ( output. status . success ( ) , langstr . compile_fail ) {
494
496
( true , true ) => {
495
497
return Err ( TestFailure :: UnexpectedCompilePass ) ;
496
498
}
497
499
( true , false ) => { }
498
500
( false , true ) => {
499
- if !lang_string . error_codes . is_empty ( ) {
501
+ if !langstr . error_codes . is_empty ( ) {
500
502
// We used to check if the output contained "error[{}]: " but since we added the
501
503
// colored output, we can't anymore because of the color escape characters before
502
504
// the ":".
503
- lang_string. error_codes . retain ( |err| !out. contains ( & format ! ( "error[{err}]" ) ) ) ;
504
-
505
- if !lang_string. error_codes . is_empty ( ) {
506
- return Err ( TestFailure :: MissingErrorCodes ( lang_string. error_codes ) ) ;
505
+ let missing_codes: Vec < String > = scraped_test
506
+ . langstr
507
+ . error_codes
508
+ . iter ( )
509
+ . filter ( |err| !out. contains ( & format ! ( "error[{err}]" ) ) )
510
+ . cloned ( )
511
+ . collect ( ) ;
512
+
513
+ if !missing_codes. is_empty ( ) {
514
+ return Err ( TestFailure :: MissingErrorCodes ( missing_codes) ) ;
507
515
}
508
516
}
509
517
}
@@ -512,7 +520,7 @@ fn run_test(
512
520
}
513
521
}
514
522
515
- if no_run {
523
+ if scraped_test . no_run ( rustdoc_options ) {
516
524
return Ok ( ( ) ) ;
517
525
}
518
526
@@ -544,9 +552,9 @@ fn run_test(
544
552
match result {
545
553
Err ( e) => return Err ( TestFailure :: ExecutionError ( e) ) ,
546
554
Ok ( out) => {
547
- if lang_string . should_panic && out. status . success ( ) {
555
+ if langstr . should_panic && out. status . success ( ) {
548
556
return Err ( TestFailure :: UnexpectedRunPass ) ;
549
- } else if !lang_string . should_panic && !out. status . success ( ) {
557
+ } else if !langstr . should_panic && !out. status . success ( ) {
550
558
return Err ( TestFailure :: ExecutionFailure ( out) ) ;
551
559
}
552
560
}
@@ -1099,19 +1107,23 @@ fn doctest_run_fn(
1099
1107
let report_unused_externs = |uext| {
1100
1108
unused_externs. lock ( ) . unwrap ( ) . push ( uext) ;
1101
1109
} ;
1102
- let no_run = scraped_test. no_run ( & rustdoc_options) ;
1103
1110
let edition = scraped_test. edition ( & rustdoc_options) ;
1104
- let res = run_test (
1111
+ let ( full_test_code , full_test_line_offset , supports_color ) = make_test (
1105
1112
& scraped_test. text ,
1106
- scraped_test. line ,
1107
- & rustdoc_options,
1108
- test_opts,
1109
- scraped_test. langstr ,
1110
- no_run,
1113
+ Some ( & global_opts. crate_name ) ,
1114
+ scraped_test. langstr . test_harness ,
1111
1115
& global_opts,
1112
1116
edition,
1113
- report_unused_externs ,
1117
+ Some ( & test_opts . test_id ) ,
1114
1118
) ;
1119
+ let runnable_test = RunnableDoctest {
1120
+ full_test_code,
1121
+ full_test_line_offset,
1122
+ test_opts,
1123
+ global_opts,
1124
+ scraped_test,
1125
+ } ;
1126
+ let res = run_test ( runnable_test, & rustdoc_options, supports_color, report_unused_externs) ;
1115
1127
1116
1128
if let Err ( err) = res {
1117
1129
match err {
0 commit comments