@@ -2,24 +2,19 @@ use rustc_data_structures::sync::Lrc;
22use rustc_interface:: interface;
33use rustc:: hir;
44use rustc:: hir:: intravisit;
5- use rustc:: hir:: def_id:: LOCAL_CRATE ;
65use rustc:: session:: { self , config, DiagnosticOutput } ;
7- use rustc:: session:: config:: { OutputType , OutputTypes , Externs , CodegenOptions } ;
8- use rustc:: session:: search_paths:: SearchPath ;
96use rustc:: util:: common:: ErrorReported ;
107use syntax:: ast;
118use syntax:: with_globals;
129use syntax:: source_map:: SourceMap ;
1310use syntax:: edition:: Edition ;
1411use syntax:: feature_gate:: UnstableFeatures ;
1512use std:: env;
16- use std:: io:: prelude:: * ;
17- use std:: io;
18- use std:: panic:: { self , AssertUnwindSafe } ;
13+ use std:: io:: { self , Write } ;
14+ use std:: panic;
1915use std:: path:: PathBuf ;
20- use std:: process:: { self , Command } ;
16+ use std:: process:: { self , Command , Stdio } ;
2117use std:: str;
22- use std:: sync:: { Arc , Mutex } ;
2318use syntax:: symbol:: sym;
2419use syntax_pos:: { BytePos , DUMMY_SP , Pos , Span , FileName } ;
2520use tempfile:: Builder as TempFileBuilder ;
@@ -89,18 +84,11 @@ pub fn run(options: Options) -> i32 {
8984 opts. display_warnings |= options. display_warnings ;
9085 let mut collector = Collector :: new (
9186 compiler. crate_name ( ) ?. peek ( ) . to_string ( ) ,
92- options. cfgs ,
93- options. libs ,
94- options. codegen_options ,
95- options. externs ,
87+ options,
9688 false ,
9789 opts,
98- options. maybe_sysroot ,
9990 Some ( compiler. source_map ( ) . clone ( ) ) ,
10091 None ,
101- options. linker ,
102- options. edition ,
103- options. persist_doctests ,
10492 ) ;
10593
10694 let mut global_ctxt = compiler. global_ctxt ( ) ?. take ( ) ;
@@ -189,20 +177,14 @@ fn run_test(
189177 cratename : & str ,
190178 filename : & FileName ,
191179 line : usize ,
192- cfgs : Vec < String > ,
193- libs : Vec < SearchPath > ,
194- cg : CodegenOptions ,
195- externs : Externs ,
180+ options : Options ,
196181 should_panic : bool ,
197182 no_run : bool ,
198183 as_test_harness : bool ,
199184 compile_fail : bool ,
200185 mut error_codes : Vec < String > ,
201186 opts : & TestOptions ,
202- maybe_sysroot : Option < PathBuf > ,
203- linker : Option < PathBuf > ,
204187 edition : Edition ,
205- persist_doctests : Option < PathBuf > ,
206188) -> Result < ( ) , TestFailure > {
207189 let ( test, line_offset) = match panic:: catch_unwind ( || {
208190 make_test ( test, Some ( cratename) , as_test_harness, opts, edition)
@@ -223,61 +205,6 @@ fn run_test(
223205 _ => PathBuf :: from ( r"doctest.rs" ) ,
224206 } ;
225207
226- let input = config:: Input :: Str {
227- name : FileName :: DocTest ( path, line as isize - line_offset as isize ) ,
228- input : test,
229- } ;
230- let outputs = OutputTypes :: new ( & [ ( OutputType :: Exe , None ) ] ) ;
231-
232- let sessopts = config:: Options {
233- maybe_sysroot,
234- search_paths : libs,
235- crate_types : vec ! [ config:: CrateType :: Executable ] ,
236- output_types : outputs,
237- externs,
238- cg : config:: CodegenOptions {
239- linker,
240- ..cg
241- } ,
242- test : as_test_harness,
243- unstable_features : UnstableFeatures :: from_environment ( ) ,
244- debugging_opts : config:: DebuggingOptions {
245- ..config:: basic_debugging_options ( )
246- } ,
247- edition,
248- ..config:: Options :: default ( )
249- } ;
250-
251- // Shuffle around a few input and output handles here. We're going to pass
252- // an explicit handle into rustc to collect output messages, but we also
253- // want to catch the error message that rustc prints when it fails.
254- //
255- // We take our thread-local stderr (likely set by the test runner) and replace
256- // it with a sink that is also passed to rustc itself. When this function
257- // returns the output of the sink is copied onto the output of our own thread.
258- //
259- // The basic idea is to not use a default Handler for rustc, and then also
260- // not print things by default to the actual stderr.
261- struct Sink ( Arc < Mutex < Vec < u8 > > > ) ;
262- impl Write for Sink {
263- fn write ( & mut self , data : & [ u8 ] ) -> io:: Result < usize > {
264- Write :: write ( & mut * self . 0 . lock ( ) . unwrap ( ) , data)
265- }
266- fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
267- }
268- struct Bomb ( Arc < Mutex < Vec < u8 > > > , Option < Box < dyn Write +Send > > ) ;
269- impl Drop for Bomb {
270- fn drop ( & mut self ) {
271- let mut old = self . 1 . take ( ) . unwrap ( ) ;
272- let _ = old. write_all ( & self . 0 . lock ( ) . unwrap ( ) ) ;
273- io:: set_panic ( Some ( old) ) ;
274- }
275- }
276- let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
277-
278- let old = io:: set_panic ( Some ( box Sink ( data. clone ( ) ) ) ) ;
279- let _bomb = Bomb ( data. clone ( ) , Some ( old. unwrap_or ( box io:: stdout ( ) ) ) ) ;
280-
281208 enum DirState {
282209 Temp ( tempfile:: TempDir ) ,
283210 Perm ( PathBuf ) ,
@@ -292,7 +219,7 @@ fn run_test(
292219 }
293220 }
294221
295- let outdir = if let Some ( mut path) = persist_doctests {
222+ let outdir = if let Some ( mut path) = options . persist_doctests {
296223 path. push ( format ! ( "{}_{}" ,
297224 filename
298225 . to_string( )
@@ -314,49 +241,73 @@ fn run_test(
314241 } ;
315242 let output_file = outdir. path ( ) . join ( "rust_out" ) ;
316243
317- let config = interface:: Config {
318- opts : sessopts,
319- crate_cfg : config:: parse_cfgspecs ( cfgs) ,
320- input,
321- input_path : None ,
322- output_file : Some ( output_file. clone ( ) ) ,
323- output_dir : None ,
324- file_loader : None ,
325- diagnostic_output : DiagnosticOutput :: Raw ( box Sink ( data. clone ( ) ) ) ,
326- stderr : Some ( data. clone ( ) ) ,
327- crate_name : None ,
328- lint_caps : Default :: default ( ) ,
329- } ;
244+ let mut compiler = Command :: new ( std:: env:: current_exe ( ) . unwrap ( ) . with_file_name ( "rustc" ) ) ;
245+ compiler. arg ( "--crate-type" ) . arg ( "bin" ) ;
246+ for cfg in & options. cfgs {
247+ compiler. arg ( "--cfg" ) . arg ( & cfg) ;
248+ }
249+ if let Some ( sysroot) = options. maybe_sysroot {
250+ compiler. arg ( "--sysroot" ) . arg ( sysroot) ;
251+ }
252+ compiler. arg ( "--edition" ) . arg ( & edition. to_string ( ) ) ;
253+ compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , path) ;
254+ compiler. env ( "UNSTABLE_RUSTDOC_TEST_LINE" ,
255+ format ! ( "{}" , line as isize - line_offset as isize ) ) ;
256+ compiler. arg ( "-o" ) . arg ( & output_file) ;
257+ if as_test_harness {
258+ compiler. arg ( "--test" ) ;
259+ }
260+ for lib_str in & options. lib_strs {
261+ compiler. arg ( "-L" ) . arg ( & lib_str) ;
262+ }
263+ for extern_str in & options. extern_strs {
264+ compiler. arg ( "--extern" ) . arg ( & extern_str) ;
265+ }
266+ for codegen_options_str in & options. codegen_options_strs {
267+ compiler. arg ( "-C" ) . arg ( & codegen_options_str) ;
268+ }
269+ if let Some ( linker) = options. linker {
270+ compiler. arg ( & format ! ( "-C linker={:?}" , linker) ) ;
271+ }
272+ if no_run {
273+ compiler. arg ( "--emit=metadata" ) ;
274+ }
330275
331- let compile_result = panic:: catch_unwind ( AssertUnwindSafe ( || {
332- interface:: run_compiler ( config, |compiler| {
333- if no_run {
334- compiler. global_ctxt ( ) . and_then ( |global_ctxt| global_ctxt. take ( ) . enter ( |tcx| {
335- tcx. analysis ( LOCAL_CRATE )
336- } ) ) . ok ( ) ;
337- } else {
338- compiler. compile ( ) . ok ( ) ;
339- } ;
340- compiler. session ( ) . compile_status ( )
341- } )
342- } ) ) . map_err ( |_| ( ) ) . and_then ( |s| s. map_err ( |_| ( ) ) ) ;
276+ compiler. arg ( "-" ) ;
277+ compiler. stdin ( Stdio :: piped ( ) ) ;
278+ compiler. stderr ( Stdio :: piped ( ) ) ;
279+
280+ let mut child = compiler. spawn ( ) . expect ( "Failed to spawn rustc process" ) ;
281+ {
282+ let stdin = child. stdin . as_mut ( ) . expect ( "Failed to open stdin" ) ;
283+ stdin. write_all ( test. as_bytes ( ) ) . expect ( "could write out test sources" ) ;
284+ }
285+ let output = child. wait_with_output ( ) . expect ( "Failed to read stdout" ) ;
343286
344- match ( compile_result, compile_fail) {
345- ( Ok ( ( ) ) , true ) => {
287+ struct Bomb < ' a > ( & ' a str ) ;
288+ impl Drop for Bomb < ' _ > {
289+ fn drop ( & mut self ) {
290+ eprint ! ( "{}" , self . 0 ) ;
291+ }
292+ }
293+
294+ let out = str:: from_utf8 ( & output. stderr ) . unwrap ( ) ;
295+ let _bomb = Bomb ( & out) ;
296+ match ( output. status . success ( ) , compile_fail) {
297+ ( true , true ) => {
346298 return Err ( TestFailure :: UnexpectedCompilePass ) ;
347299 }
348- ( Ok ( ( ) ) , false ) => { }
349- ( Err ( _ ) , true ) => {
300+ ( true , false ) => { }
301+ ( false , true ) => {
350302 if !error_codes. is_empty ( ) {
351- let out = String :: from_utf8 ( data. lock ( ) . unwrap ( ) . to_vec ( ) ) . unwrap ( ) ;
352303 error_codes. retain ( |err| !out. contains ( err) ) ;
353304
354305 if !error_codes. is_empty ( ) {
355306 return Err ( TestFailure :: MissingErrorCodes ( error_codes) ) ;
356307 }
357308 }
358309 }
359- ( Err ( _ ) , false ) => {
310+ ( false , false ) => {
360311 return Err ( TestFailure :: CompileError ) ;
361312 }
362313 }
@@ -652,45 +603,28 @@ pub struct Collector {
652603 // the `names` vector of that test will be `["Title", "Subtitle"]`.
653604 names : Vec < String > ,
654605
655- cfgs : Vec < String > ,
656- libs : Vec < SearchPath > ,
657- cg : CodegenOptions ,
658- externs : Externs ,
606+ options : Options ,
659607 use_headers : bool ,
660608 cratename : String ,
661609 opts : TestOptions ,
662- maybe_sysroot : Option < PathBuf > ,
663610 position : Span ,
664611 source_map : Option < Lrc < SourceMap > > ,
665612 filename : Option < PathBuf > ,
666- linker : Option < PathBuf > ,
667- edition : Edition ,
668- persist_doctests : Option < PathBuf > ,
669613}
670614
671615impl Collector {
672- pub fn new ( cratename : String , cfgs : Vec < String > , libs : Vec < SearchPath > , cg : CodegenOptions ,
673- externs : Externs , use_headers : bool , opts : TestOptions ,
674- maybe_sysroot : Option < PathBuf > , source_map : Option < Lrc < SourceMap > > ,
675- filename : Option < PathBuf > , linker : Option < PathBuf > , edition : Edition ,
676- persist_doctests : Option < PathBuf > ) -> Collector {
616+ pub fn new ( cratename : String , options : Options , use_headers : bool , opts : TestOptions ,
617+ source_map : Option < Lrc < SourceMap > > , filename : Option < PathBuf > , ) -> Collector {
677618 Collector {
678619 tests : Vec :: new ( ) ,
679620 names : Vec :: new ( ) ,
680- cfgs,
681- libs,
682- cg,
683- externs,
621+ options,
684622 use_headers,
685623 cratename,
686624 opts,
687- maybe_sysroot,
688625 position : DUMMY_SP ,
689626 source_map,
690627 filename,
691- linker,
692- edition,
693- persist_doctests,
694628 }
695629 }
696630
@@ -725,16 +659,10 @@ impl Tester for Collector {
725659 fn add_test ( & mut self , test : String , config : LangString , line : usize ) {
726660 let filename = self . get_filename ( ) ;
727661 let name = self . generate_name ( line, & filename) ;
728- let cfgs = self . cfgs . clone ( ) ;
729- let libs = self . libs . clone ( ) ;
730- let cg = self . cg . clone ( ) ;
731- let externs = self . externs . clone ( ) ;
732662 let cratename = self . cratename . to_string ( ) ;
733663 let opts = self . opts . clone ( ) ;
734- let maybe_sysroot = self . maybe_sysroot . clone ( ) ;
735- let linker = self . linker . clone ( ) ;
736- let edition = config. edition . unwrap_or ( self . edition ) ;
737- let persist_doctests = self . persist_doctests . clone ( ) ;
664+ let edition = config. edition . unwrap_or ( self . options . edition . clone ( ) ) ;
665+ let options = self . options . clone ( ) ;
738666
739667 debug ! ( "creating test {}: {}" , name, test) ;
740668 self . tests . push ( testing:: TestDescAndFn {
@@ -751,20 +679,14 @@ impl Tester for Collector {
751679 & cratename,
752680 & filename,
753681 line,
754- cfgs,
755- libs,
756- cg,
757- externs,
682+ options,
758683 config. should_panic ,
759684 config. no_run ,
760685 config. test_harness ,
761686 config. compile_fail ,
762687 config. error_codes ,
763688 & opts,
764- maybe_sysroot,
765- linker,
766689 edition,
767- persist_doctests
768690 ) ;
769691
770692 if let Err ( err) = res {
0 commit comments