@@ -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
@@ -743,31 +787,40 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
743
787
eprintln ! ( "[cargo-miri runner] {:?}" , cmd) ;
744
788
}
745
789
746
- cmd. stdin ( std:: process:: Stdio :: piped ( ) ) ;
747
- let mut child = cmd. spawn ( ) . expect ( "failed to spawn miri process" ) ;
748
- {
749
- let stdin = child. stdin . as_mut ( ) . expect ( "failed to open stdin" ) ;
750
- stdin. write_all ( & info. stdin ) . expect ( "failed to write out test source" ) ;
751
- }
752
- let exit_status = child. wait ( ) . expect ( "failed to run command" ) ;
753
- if exit_status. success ( ) . not ( ) {
754
- std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
755
- }
790
+ exec_with_pipe ( cmd, & info. stdin )
756
791
}
757
792
758
- fn phase_cargo_rustdoc ( fst_arg : & str , args : env:: Args ) {
793
+ fn phase_cargo_rustdoc ( fst_arg : & str , mut args : env:: Args ) {
759
794
let verbose = std:: env:: var_os ( "MIRI_VERBOSE" ) . is_some ( ) ;
760
795
761
796
// phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here;
762
797
// just default to a straight-forward invocation for now:
763
798
let mut cmd = Command :: new ( OsString :: from ( "rustdoc" ) ) ;
764
799
765
- // just pass everything through until we find a reason not to do that:
800
+ let extern_flag = "--extern" ;
801
+ assert ! ( fst_arg != extern_flag) ;
766
802
cmd. arg ( fst_arg) ;
767
- cmd. args ( args) ;
768
803
769
- cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
804
+ // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
805
+ while let Some ( arg) = args. next ( ) {
806
+ if arg == extern_flag {
807
+ cmd. arg ( extern_flag) ; // always forward flag, but adjust filename
808
+ // `--extern` is always passed as a separate argument by cargo.
809
+ let next_arg = args. next ( ) . expect ( "`--extern` should be followed by a filename" ) ;
810
+ if let Some ( next_lib) = next_arg. strip_suffix ( ".rlib" ) {
811
+ // If this is an rlib, make it an rmeta.
812
+ cmd. arg ( format ! ( "{}.rmeta" , next_lib) ) ;
813
+ } else {
814
+ // Some other extern file (e.g., a `.so`). Forward unchanged.
815
+ cmd. arg ( next_arg) ;
816
+ }
817
+ } else {
818
+ cmd. arg ( arg) ;
819
+ }
820
+ }
770
821
822
+ cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
823
+
771
824
let cargo_miri_path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
772
825
cmd. arg ( "--test-builder" ) . arg ( & cargo_miri_path) ;
773
826
cmd. arg ( "--runtool" ) . arg ( & cargo_miri_path) ;
0 commit comments