@@ -58,8 +58,16 @@ use std::str;
5858use std:: sync:: LazyLock ;
5959use std:: time:: Instant ;
6060
61+ // This import blocks the use of panicking `print` and `println` in all the code
62+ // below. Please use `safe_print` and `safe_println` to avoid ICE when
63+ // encountering an I/O error during print.
64+ #[ allow( unused_imports) ]
65+ use std:: { compile_error as print, compile_error as println} ;
66+
6167pub mod args;
6268pub mod pretty;
69+ #[ macro_use]
70+ mod print;
6371mod session_diagnostics;
6472
6573use crate :: session_diagnostics:: {
@@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
511519 if io:: stdout ( ) . is_terminal ( ) {
512520 show_content_with_pager ( & text) ;
513521 } else {
514- print ! ( "{text}" ) ;
522+ safe_print ! ( "{text}" ) ;
515523 }
516524 }
517525 Err ( InvalidErrorCode ) => {
@@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) {
547555 // If pager fails for whatever reason, we should still print the content
548556 // to standard output
549557 if fallback_to_println {
550- print ! ( "{content}" ) ;
558+ safe_print ! ( "{content}" ) ;
551559 }
552560}
553561
@@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co
601609 let path = & ( * ifile) ;
602610 let mut v = Vec :: new ( ) ;
603611 locator:: list_file_metadata ( & sess. target , path, metadata_loader, & mut v) . unwrap ( ) ;
604- println ! ( "{}" , String :: from_utf8( v) . unwrap( ) ) ;
612+ safe_println ! ( "{}" , String :: from_utf8( v) . unwrap( ) ) ;
605613 }
606614 Input :: Str { .. } => {
607615 early_error ( ErrorOutputType :: default ( ) , "cannot list metadata for stdin" ) ;
@@ -642,12 +650,12 @@ fn print_crate_info(
642650 TargetList => {
643651 let mut targets = rustc_target:: spec:: TARGETS . to_vec ( ) ;
644652 targets. sort_unstable ( ) ;
645- println ! ( "{}" , targets. join( "\n " ) ) ;
653+ safe_println ! ( "{}" , targets. join( "\n " ) ) ;
646654 }
647- Sysroot => println ! ( "{}" , sess. sysroot. display( ) ) ,
648- TargetLibdir => println ! ( "{}" , sess. target_tlib_path. dir. display( ) ) ,
655+ Sysroot => safe_println ! ( "{}" , sess. sysroot. display( ) ) ,
656+ TargetLibdir => safe_println ! ( "{}" , sess. target_tlib_path. dir. display( ) ) ,
649657 TargetSpec => {
650- println ! ( "{}" , serde_json:: to_string_pretty( & sess. target. to_json( ) ) . unwrap( ) ) ;
658+ safe_println ! ( "{}" , serde_json:: to_string_pretty( & sess. target. to_json( ) ) . unwrap( ) ) ;
651659 }
652660 AllTargetSpecs => {
653661 let mut targets = BTreeMap :: new ( ) ;
@@ -656,7 +664,7 @@ fn print_crate_info(
656664 let target = Target :: expect_builtin ( & triple) ;
657665 targets. insert ( name, target. to_json ( ) ) ;
658666 }
659- println ! ( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
667+ safe_println ! ( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
660668 }
661669 FileNames | CrateName => {
662670 let Some ( attrs) = attrs. as_ref ( ) else {
@@ -666,14 +674,14 @@ fn print_crate_info(
666674 let t_outputs = rustc_interface:: util:: build_output_filenames ( attrs, sess) ;
667675 let id = rustc_session:: output:: find_crate_name ( sess, attrs) ;
668676 if * req == PrintRequest :: CrateName {
669- println ! ( "{id}" ) ;
677+ safe_println ! ( "{id}" ) ;
670678 continue ;
671679 }
672680 let crate_types = collect_crate_types ( sess, attrs) ;
673681 for & style in & crate_types {
674682 let fname =
675683 rustc_session:: output:: filename_for_input ( sess, style, id, & t_outputs) ;
676- println ! ( "{}" , fname. file_name( ) . unwrap( ) . to_string_lossy( ) ) ;
684+ safe_println ! ( "{}" , fname. file_name( ) . unwrap( ) . to_string_lossy( ) ) ;
677685 }
678686 }
679687 Cfg => {
@@ -707,13 +715,13 @@ fn print_crate_info(
707715
708716 cfgs. sort ( ) ;
709717 for cfg in cfgs {
710- println ! ( "{cfg}" ) ;
718+ safe_println ! ( "{cfg}" ) ;
711719 }
712720 }
713721 CallingConventions => {
714722 let mut calling_conventions = rustc_target:: spec:: abi:: all_names ( ) ;
715723 calling_conventions. sort_unstable ( ) ;
716- println ! ( "{}" , calling_conventions. join( "\n " ) ) ;
724+ safe_println ! ( "{}" , calling_conventions. join( "\n " ) ) ;
717725 }
718726 RelocationModels
719727 | CodeModels
@@ -733,7 +741,7 @@ fn print_crate_info(
733741 let stable = sess. target . options . supported_split_debuginfo . contains ( split) ;
734742 let unstable_ok = sess. unstable_options ( ) ;
735743 if stable || unstable_ok {
736- println ! ( "{split}" ) ;
744+ safe_println ! ( "{split}" ) ;
737745 }
738746 }
739747 }
@@ -770,14 +778,14 @@ pub fn version_at_macro_invocation(
770778) {
771779 let verbose = matches. opt_present ( "verbose" ) ;
772780
773- println ! ( "{binary} {version}" ) ;
781+ safe_println ! ( "{binary} {version}" ) ;
774782
775783 if verbose {
776- println ! ( "binary: {binary}" ) ;
777- println ! ( "commit-hash: {commit_hash}" ) ;
778- println ! ( "commit-date: {commit_date}" ) ;
779- println ! ( "host: {}" , config:: host_triple( ) ) ;
780- println ! ( "release: {release}" ) ;
784+ safe_println ! ( "binary: {binary}" ) ;
785+ safe_println ! ( "commit-hash: {commit_hash}" ) ;
786+ safe_println ! ( "commit-date: {commit_date}" ) ;
787+ safe_println ! ( "host: {}" , config:: host_triple( ) ) ;
788+ safe_println ! ( "release: {release}" ) ;
781789
782790 let debug_flags = matches. opt_strs ( "Z" ) ;
783791 let backend_name = debug_flags. iter ( ) . find_map ( |x| x. strip_prefix ( "codegen-backend=" ) ) ;
@@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
807815 } else {
808816 ""
809817 } ;
810- println ! (
818+ safe_println ! (
811819 "{options}{at_path}\n Additional help:
812820 -C help Print codegen options
813821 -W help \
@@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
820828}
821829
822830fn print_wall_help ( ) {
823- println ! (
831+ safe_println ! (
824832 "
825833The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
826834default. Use `rustc -W help` to see all available lints. It's more common to put
@@ -832,7 +840,7 @@ the command line flag directly.
832840
833841/// Write to stdout lint command options, together with a list of all available lints
834842pub fn describe_lints ( sess : & Session , lint_store : & LintStore , loaded_plugins : bool ) {
835- println ! (
843+ safe_println ! (
836844 "
837845Available lint options:
838846 -W <foo> Warn about <foo>
@@ -877,21 +885,21 @@ Available lint options:
877885 s
878886 } ;
879887
880- println ! ( "Lint checks provided by rustc:\n " ) ;
888+ safe_println ! ( "Lint checks provided by rustc:\n " ) ;
881889
882890 let print_lints = |lints : Vec < & Lint > | {
883- println ! ( " {} {:7.7} {}" , padded( "name" ) , "default" , "meaning" ) ;
884- println ! ( " {} {:7.7} {}" , padded( "----" ) , "-------" , "-------" ) ;
891+ safe_println ! ( " {} {:7.7} {}" , padded( "name" ) , "default" , "meaning" ) ;
892+ safe_println ! ( " {} {:7.7} {}" , padded( "----" ) , "-------" , "-------" ) ;
885893 for lint in lints {
886894 let name = lint. name_lower ( ) . replace ( '_' , "-" ) ;
887- println ! (
895+ safe_println ! (
888896 " {} {:7.7} {}" ,
889897 padded( & name) ,
890898 lint. default_level( sess. edition( ) ) . as_str( ) ,
891899 lint. desc
892900 ) ;
893901 }
894- println ! ( "\n " ) ;
902+ safe_println ! ( "\n " ) ;
895903 } ;
896904
897905 print_lints ( builtin) ;
@@ -912,14 +920,14 @@ Available lint options:
912920 s
913921 } ;
914922
915- println ! ( "Lint groups provided by rustc:\n " ) ;
923+ safe_println ! ( "Lint groups provided by rustc:\n " ) ;
916924
917925 let print_lint_groups = |lints : Vec < ( & ' static str , Vec < LintId > ) > , all_warnings| {
918- println ! ( " {} sub-lints" , padded( "name" ) ) ;
919- println ! ( " {} ---------" , padded( "----" ) ) ;
926+ safe_println ! ( " {} sub-lints" , padded( "name" ) ) ;
927+ safe_println ! ( " {} ---------" , padded( "----" ) ) ;
920928
921929 if all_warnings {
922- println ! ( " {} all lints that are set to issue warnings" , padded( "warnings" ) ) ;
930+ safe_println ! ( " {} all lints that are set to issue warnings" , padded( "warnings" ) ) ;
923931 }
924932
925933 for ( name, to) in lints {
@@ -929,26 +937,26 @@ Available lint options:
929937 . map ( |x| x. to_string ( ) . replace ( '_' , "-" ) )
930938 . collect :: < Vec < String > > ( )
931939 . join ( ", " ) ;
932- println ! ( " {} {}" , padded( & name) , desc) ;
940+ safe_println ! ( " {} {}" , padded( & name) , desc) ;
933941 }
934- println ! ( "\n " ) ;
942+ safe_println ! ( "\n " ) ;
935943 } ;
936944
937945 print_lint_groups ( builtin_groups, true ) ;
938946
939947 match ( loaded_plugins, plugin. len ( ) , plugin_groups. len ( ) ) {
940948 ( false , 0 , _) | ( false , _, 0 ) => {
941- println ! ( "Lint tools like Clippy can provide additional lints and lint groups." ) ;
949+ safe_println ! ( "Lint tools like Clippy can provide additional lints and lint groups." ) ;
942950 }
943951 ( false , ..) => panic ! ( "didn't load lint plugins but got them anyway!" ) ,
944- ( true , 0 , 0 ) => println ! ( "This crate does not load any lint plugins or lint groups." ) ,
952+ ( true , 0 , 0 ) => safe_println ! ( "This crate does not load any lint plugins or lint groups." ) ,
945953 ( true , l, g) => {
946954 if l > 0 {
947- println ! ( "Lint checks provided by plugins loaded by this crate:\n " ) ;
955+ safe_println ! ( "Lint checks provided by plugins loaded by this crate:\n " ) ;
948956 print_lints ( plugin) ;
949957 }
950958 if g > 0 {
951- println ! ( "Lint groups provided by plugins loaded by this crate:\n " ) ;
959+ safe_println ! ( "Lint groups provided by plugins loaded by this crate:\n " ) ;
952960 print_lint_groups ( plugin_groups, false ) ;
953961 }
954962 }
@@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool {
9961004}
9971005
9981006fn describe_debug_flags ( ) {
999- println ! ( "\n Available options:\n " ) ;
1007+ safe_println ! ( "\n Available options:\n " ) ;
10001008 print_flag_list ( "-Z" , config:: Z_OPTIONS ) ;
10011009}
10021010
10031011fn describe_codegen_flags ( ) {
1004- println ! ( "\n Available codegen options:\n " ) ;
1012+ safe_println ! ( "\n Available codegen options:\n " ) ;
10051013 print_flag_list ( "-C" , config:: CG_OPTIONS ) ;
10061014}
10071015
@@ -1012,7 +1020,7 @@ fn print_flag_list<T>(
10121020 let max_len = flag_list. iter ( ) . map ( |& ( name, _, _, _) | name. chars ( ) . count ( ) ) . max ( ) . unwrap_or ( 0 ) ;
10131021
10141022 for & ( name, _, _, desc) in flag_list {
1015- println ! (
1023+ safe_println ! (
10161024 " {} {:>width$}=val -- {}" ,
10171025 cmdline_opt,
10181026 name. replace( '_' , "-" ) ,
0 commit comments