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