@@ -157,6 +157,22 @@ fn exec(mut cmd: Command) {
157
157
}
158
158
}
159
159
160
+ /// Execute the command and pipe `input` into its stdin.
161
+ /// If it fails, fail this process with the same exit code.
162
+ /// Otherwise, continue.
163
+ fn exec_with_pipe ( mut cmd : Command , input : & [ u8 ] ) {
164
+ cmd. stdin ( std:: process:: Stdio :: piped ( ) ) ;
165
+ let mut child = cmd. spawn ( ) . expect ( "failed to spawn process" ) ;
166
+ {
167
+ let stdin = child. stdin . as_mut ( ) . expect ( "failed to open stdin" ) ;
168
+ stdin. write_all ( input) . expect ( "failed to write out test source" ) ;
169
+ }
170
+ let exit_status = child. wait ( ) . expect ( "failed to run command" ) ;
171
+ if exit_status. success ( ) . not ( ) {
172
+ std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
173
+ }
174
+ }
175
+
160
176
fn xargo_version ( ) -> Option < ( u32 , u32 , u32 ) > {
161
177
let out = xargo_check ( ) . arg ( "--version" ) . output ( ) . ok ( ) ?;
162
178
if !out. status . success ( ) {
@@ -598,6 +614,34 @@ fn phase_cargo_rustc(args: env::Args) {
598
614
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
599
615
info. store ( & out_filename ( "" , ".exe" ) ) ;
600
616
617
+ // Rustdoc expects us to exit with an error code if the test is marked as `compile_fail`,
618
+ // so we need to run Miri with `MIRI_BE_RUSTC` for a check-only build.
619
+ if std:: env:: var_os ( "MIRI_CALLED_FROM_RUSTDOC" ) . is_some ( ) {
620
+ let mut cmd = miri ( ) ;
621
+
622
+ // use our own sysroot
623
+ if !has_arg_flag ( "--sysroot" ) {
624
+ let sysroot = env:: var_os ( "MIRI_SYSROOT" )
625
+ . expect ( "the wrapper should have set MIRI_SYSROOT" ) ;
626
+ cmd. arg ( "--sysroot" ) . arg ( sysroot) ;
627
+ }
628
+
629
+ // don't go into "code generation" (i.e. validation)
630
+ if info. args . iter ( ) . position ( |arg| arg. starts_with ( "--emit=" ) ) . is_none ( ) {
631
+ cmd. arg ( "--emit=dep-info,metadata" ) ;
632
+ }
633
+
634
+ cmd. args ( info. args ) ;
635
+ cmd. env ( "MIRI_BE_RUSTC" , "1" ) ;
636
+
637
+ if verbose {
638
+ eprintln ! ( "[cargo-miri rustc] captured input:\n {}" , std:: str :: from_utf8( & info. stdin) . unwrap( ) ) ;
639
+ eprintln ! ( "[cargo-miri rustc] {:?}" , cmd) ;
640
+ }
641
+
642
+ exec_with_pipe ( cmd, & info. stdin ) ;
643
+ }
644
+
601
645
return ;
602
646
}
603
647
@@ -748,31 +792,40 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
748
792
eprintln ! ( "[cargo-miri runner] {:?}" , cmd) ;
749
793
}
750
794
751
- cmd. stdin ( std:: process:: Stdio :: piped ( ) ) ;
752
- let mut child = cmd. spawn ( ) . expect ( "failed to spawn miri process" ) ;
753
- {
754
- let stdin = child. stdin . as_mut ( ) . expect ( "failed to open stdin" ) ;
755
- stdin. write_all ( & info. stdin ) . expect ( "failed to write out test source" ) ;
756
- }
757
- let exit_status = child. wait ( ) . expect ( "failed to run command" ) ;
758
- if exit_status. success ( ) . not ( ) {
759
- std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
760
- }
795
+ exec_with_pipe ( cmd, & info. stdin )
761
796
}
762
797
763
- fn phase_cargo_rustdoc ( fst_arg : & str , args : env:: Args ) {
798
+ fn phase_cargo_rustdoc ( fst_arg : & str , mut args : env:: Args ) {
764
799
let verbose = std:: env:: var_os ( "MIRI_VERBOSE" ) . is_some ( ) ;
765
800
766
801
// phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here;
767
802
// just default to a straight-forward invocation for now:
768
803
let mut cmd = Command :: new ( OsString :: from ( "rustdoc" ) ) ;
769
804
770
- // just pass everything through until we find a reason not to do that:
805
+ let extern_flag = "--extern" ;
806
+ assert ! ( fst_arg != extern_flag) ;
771
807
cmd. arg ( fst_arg) ;
772
- cmd. args ( args) ;
773
808
774
- cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
809
+ // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
810
+ while let Some ( arg) = args. next ( ) {
811
+ if arg == extern_flag {
812
+ cmd. arg ( extern_flag) ; // always forward flag, but adjust filename
813
+ // `--extern` is always passed as a separate argument by cargo.
814
+ let next_arg = args. next ( ) . expect ( "`--extern` should be followed by a filename" ) ;
815
+ if let Some ( next_lib) = next_arg. strip_suffix ( ".rlib" ) {
816
+ // If this is an rlib, make it an rmeta.
817
+ cmd. arg ( format ! ( "{}.rmeta" , next_lib) ) ;
818
+ } else {
819
+ // Some other extern file (e.g., a `.so`). Forward unchanged.
820
+ cmd. arg ( next_arg) ;
821
+ }
822
+ } else {
823
+ cmd. arg ( arg) ;
824
+ }
825
+ }
775
826
827
+ cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
828
+
776
829
let cargo_miri_path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
777
830
cmd. arg ( "--test-builder" ) . arg ( & cargo_miri_path) ;
778
831
cmd. arg ( "--runtool" ) . arg ( & cargo_miri_path) ;
0 commit comments