@@ -13,6 +13,7 @@ use rustc_span::source_map::SourceMap;
13
13
use rustc_span:: symbol:: sym;
14
14
use rustc_span:: { BytePos , FileName , Pos , Span , DUMMY_SP } ;
15
15
use rustc_target:: spec:: TargetTriple ;
16
+ use std:: collections:: HashMap ;
16
17
use std:: env;
17
18
use std:: io:: { self , Write } ;
18
19
use std:: panic;
@@ -190,10 +191,23 @@ enum TestFailure {
190
191
UnexpectedRunPass ,
191
192
}
192
193
194
+ enum DirState {
195
+ Temp ( tempfile:: TempDir ) ,
196
+ Perm ( PathBuf ) ,
197
+ }
198
+
199
+ impl DirState {
200
+ fn path ( & self ) -> & std:: path:: Path {
201
+ match self {
202
+ DirState :: Temp ( t) => t. path ( ) ,
203
+ DirState :: Perm ( p) => p. as_path ( ) ,
204
+ }
205
+ }
206
+ }
207
+
193
208
fn run_test (
194
209
test : & str ,
195
210
cratename : & str ,
196
- filename : & FileName ,
197
211
line : usize ,
198
212
options : Options ,
199
213
should_panic : bool ,
@@ -206,47 +220,11 @@ fn run_test(
206
220
mut error_codes : Vec < String > ,
207
221
opts : & TestOptions ,
208
222
edition : Edition ,
223
+ outdir : DirState ,
224
+ path : PathBuf ,
209
225
) -> Result < ( ) , TestFailure > {
210
226
let ( test, line_offset) = make_test ( test, Some ( cratename) , as_test_harness, opts, edition) ;
211
227
212
- // FIXME(#44940): if doctests ever support path remapping, then this filename
213
- // needs to be the result of `SourceMap::span_to_unmapped_path`.
214
- let path = match filename {
215
- FileName :: Real ( path) => path. clone ( ) ,
216
- _ => PathBuf :: from ( r"doctest.rs" ) ,
217
- } ;
218
-
219
- enum DirState {
220
- Temp ( tempfile:: TempDir ) ,
221
- Perm ( PathBuf ) ,
222
- }
223
-
224
- impl DirState {
225
- fn path ( & self ) -> & std:: path:: Path {
226
- match self {
227
- DirState :: Temp ( t) => t. path ( ) ,
228
- DirState :: Perm ( p) => p. as_path ( ) ,
229
- }
230
- }
231
- }
232
-
233
- let outdir = if let Some ( mut path) = options. persist_doctests {
234
- path. push ( format ! (
235
- "{}_{}" ,
236
- filename. to_string( ) . rsplit( '/' ) . next( ) . unwrap( ) . replace( "." , "_" ) ,
237
- line
238
- ) ) ;
239
- std:: fs:: create_dir_all ( & path) . expect ( "Couldn't create directory for doctest executables" ) ;
240
-
241
- DirState :: Perm ( path)
242
- } else {
243
- DirState :: Temp (
244
- TempFileBuilder :: new ( )
245
- . prefix ( "rustdoctest" )
246
- . tempdir ( )
247
- . expect ( "rustdoc needs a tempdir" ) ,
248
- )
249
- } ;
250
228
let output_file = outdir. path ( ) . join ( "rust_out" ) ;
251
229
252
230
let rustc_binary = options
@@ -639,6 +617,7 @@ pub struct Collector {
639
617
position : Span ,
640
618
source_map : Option < Lrc < SourceMap > > ,
641
619
filename : Option < PathBuf > ,
620
+ visited_tests : HashMap < ( String , usize ) , usize > ,
642
621
}
643
622
644
623
impl Collector {
@@ -662,6 +641,7 @@ impl Collector {
662
641
position : DUMMY_SP ,
663
642
source_map,
664
643
filename,
644
+ visited_tests : HashMap :: new ( ) ,
665
645
}
666
646
}
667
647
@@ -705,6 +685,48 @@ impl Tester for Collector {
705
685
let target = self . options . target . clone ( ) ;
706
686
let target_str = target. to_string ( ) ;
707
687
688
+ // FIXME(#44940): if doctests ever support path remapping, then this filename
689
+ // needs to be the result of `SourceMap::span_to_unmapped_path`.
690
+ let path = match & filename {
691
+ FileName :: Real ( path) => path. clone ( ) ,
692
+ _ => PathBuf :: from ( r"doctest.rs" ) ,
693
+ } ;
694
+
695
+ let outdir = if let Some ( mut path) = options. persist_doctests . clone ( ) {
696
+ // For example `module/file.rs` would become `module_file_rs`
697
+ let folder_name = filename
698
+ . to_string ( )
699
+ . chars ( )
700
+ . map ( |c| if c == '/' || c == '.' { '_' } else { c } )
701
+ . collect :: < String > ( ) ;
702
+
703
+ path. push ( format ! (
704
+ "{name}_{line}_{number}" ,
705
+ name = folder_name,
706
+ number = {
707
+ // Increases the current test number, if this file already
708
+ // exists or it creates a new entry with a test number of 0.
709
+ self . visited_tests
710
+ . entry( ( folder_name. clone( ) , line) )
711
+ . and_modify( |v| * v += 1 )
712
+ . or_insert( 0 )
713
+ } ,
714
+ line = line,
715
+ ) ) ;
716
+
717
+ std:: fs:: create_dir_all ( & path)
718
+ . expect ( "Couldn't create directory for doctest executables" ) ;
719
+
720
+ DirState :: Perm ( path)
721
+ } else {
722
+ DirState :: Temp (
723
+ TempFileBuilder :: new ( )
724
+ . prefix ( "rustdoctest" )
725
+ . tempdir ( )
726
+ . expect ( "rustdoc needs a tempdir" ) ,
727
+ )
728
+ } ;
729
+
708
730
debug ! ( "creating test {}: {}" , name, test) ;
709
731
self . tests . push ( testing:: TestDescAndFn {
710
732
desc : testing:: TestDesc {
@@ -723,7 +745,6 @@ impl Tester for Collector {
723
745
let res = run_test (
724
746
& test,
725
747
& cratename,
726
- & filename,
727
748
line,
728
749
options,
729
750
config. should_panic ,
@@ -736,6 +757,8 @@ impl Tester for Collector {
736
757
config. error_codes ,
737
758
& opts,
738
759
edition,
760
+ outdir,
761
+ path,
739
762
) ;
740
763
741
764
if let Err ( err) = res {
0 commit comments