@@ -51,7 +51,8 @@ use std::cmp::max;
5151use std:: collections:: BTreeMap ;
5252use std:: env;
5353use std:: ffi:: OsString ;
54- use std:: fs;
54+ use std:: fmt;
55+ use std:: fs:: { self , File } ;
5556use std:: io:: { self , IsTerminal , Read , Write } ;
5657use std:: panic:: { self , catch_unwind} ;
5758use std:: path:: PathBuf ;
@@ -67,6 +68,11 @@ macro do_not_use_print($($t:tt)*) {
6768 )
6869}
6970
71+ #[ allow( unused_macros) ]
72+ macro do_not_use_safe_print( $( $t: tt) * ) {
73+ std:: compile_error!( "Don't use `safe_print` or `safe_println` here, use `println_info` instead" )
74+ }
75+
7076// This import blocks the use of panicking `print` and `println` in all the code
7177// below. Please use `safe_print` and `safe_println` to avoid ICE when
7278// encountering an I/O error during print.
@@ -718,6 +724,13 @@ fn print_crate_info(
718724 parse_attrs: bool ,
719725) -> Compilation {
720726 use rustc_session:: config:: PrintRequest :: * ;
727+
728+ // This import prevents the following code from using the printing macros
729+ // used by the rest of the module. Within this function, we only write to
730+ // the output specified by `sess.io.output_file`.
731+ #[ allow( unused_imports) ]
732+ use { do_not_use_safe_print as safe_print, do_not_use_safe_print as safe_println} ;
733+
721734 // NativeStaticLibs and LinkArgs are special - printed during linking
722735 // (empty iterator returns true)
723736 if sess. opts. prints. iter( ) . all( |& p| p == NativeStaticLibs || p == LinkArgs ) {
@@ -736,17 +749,42 @@ fn print_crate_info(
736749 } else {
737750 None
738751 } ;
752+
753+ let mut output_io: Box <dyn Write > = match & sess. io. output_file {
754+ Some ( OutFileName :: Real ( output_file_path) ) => match File :: create( output_file_path) {
755+ Ok ( output_file) => Box :: new( output_file) ,
756+ Err ( err) => handler. early_error( format!(
757+ "failed to create {}: {}" ,
758+ output_file_path. display( ) ,
759+ err,
760+ ) ) ,
761+ } ,
762+ None | Some ( OutFileName :: Stdout ) => Box :: new( io:: stdout( ) ) ,
763+ } ;
764+
765+ fn write_output( output_io: & mut dyn Write , args: fmt:: Arguments <' _>) {
766+ if let Err ( _) = output_io. write_fmt( args) {
767+ rustc_errors:: FatalError . raise( ) ;
768+ }
769+ }
770+
771+ macro_rules! println_info {
772+ ( $( $arg: tt) * ) => {
773+ write_output( & mut * output_io, format_args!( "{}\n " , format_args!( $( $arg) * ) ) )
774+ } ;
775+ }
776+
739777 for req in & sess. opts. prints {
740778 match * req {
741779 TargetList => {
742780 let mut targets = rustc_target:: spec:: TARGETS . to_vec( ) ;
743781 targets. sort_unstable( ) ;
744- safe_println ! ( "{}" , targets. join( "\n " ) ) ;
782+ println_info !( "{}" , targets. join( "\n " ) ) ;
745783 }
746- Sysroot => safe_println ! ( "{}" , sess. sysroot. display( ) ) ,
747- TargetLibdir => safe_println ! ( "{}" , sess. target_tlib_path. dir. display( ) ) ,
784+ Sysroot => println_info !( "{}" , sess. sysroot. display( ) ) ,
785+ TargetLibdir => println_info !( "{}" , sess. target_tlib_path. dir. display( ) ) ,
748786 TargetSpec => {
749- safe_println ! ( "{}" , serde_json:: to_string_pretty( & sess. target. to_json( ) ) . unwrap( ) ) ;
787+ println_info !( "{}" , serde_json:: to_string_pretty( & sess. target. to_json( ) ) . unwrap( ) ) ;
750788 }
751789 AllTargetSpecs => {
752790 let mut targets = BTreeMap :: new( ) ;
@@ -755,7 +793,7 @@ fn print_crate_info(
755793 let target = Target :: expect_builtin( & triple) ;
756794 targets. insert( name, target. to_json( ) ) ;
757795 }
758- safe_println ! ( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
796+ println_info !( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
759797 }
760798 FileNames | CrateName => {
761799 let Some ( attrs) = attrs. as_ref( ) else {
@@ -765,14 +803,14 @@ fn print_crate_info(
765803 let t_outputs = rustc_interface:: util:: build_output_filenames( attrs, sess) ;
766804 let id = rustc_session:: output:: find_crate_name( sess, attrs) ;
767805 if * req == PrintRequest :: CrateName {
768- safe_println ! ( "{id}" ) ;
806+ println_info !( "{id}" ) ;
769807 continue ;
770808 }
771809 let crate_types = collect_crate_types( sess, attrs) ;
772810 for & style in & crate_types {
773811 let fname =
774812 rustc_session:: output:: filename_for_input( sess, style, id, & t_outputs) ;
775- safe_println ! ( "{}" , fname. as_path( ) . file_name( ) . unwrap( ) . to_string_lossy( ) ) ;
813+ println_info !( "{}" , fname. as_path( ) . file_name( ) . unwrap( ) . to_string_lossy( ) ) ;
776814 }
777815 }
778816 Cfg => {
@@ -806,13 +844,13 @@ fn print_crate_info(
806844
807845 cfgs. sort( ) ;
808846 for cfg in cfgs {
809- safe_println ! ( "{cfg}" ) ;
847+ println_info !( "{cfg}" ) ;
810848 }
811849 }
812850 CallingConventions => {
813851 let mut calling_conventions = rustc_target:: spec:: abi:: all_names( ) ;
814852 calling_conventions. sort_unstable( ) ;
815- safe_println ! ( "{}" , calling_conventions. join( "\n " ) ) ;
853+ println_info !( "{}" , calling_conventions. join( "\n " ) ) ;
816854 }
817855 RelocationModels
818856 | CodeModels
@@ -830,15 +868,15 @@ fn print_crate_info(
830868
831869 for split in & [ Off , Packed , Unpacked ] {
832870 if sess. target. options. supported_split_debuginfo. contains( split) {
833- safe_println ! ( "{split}" ) ;
871+ println_info !( "{split}" ) ;
834872 }
835873 }
836874 }
837875 DeploymentTarget => {
838876 use rustc_target:: spec:: current_apple_deployment_target;
839877
840878 if sess. target. is_like_osx {
841- safe_println ! (
879+ println_info !(
842880 "deployment_target={}" ,
843881 current_apple_deployment_target( & sess. target)
844882 . expect( "unknown Apple target OS" )
0 commit comments