@@ -228,8 +228,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
228228
229229 let args = args:: arg_expand_all( & default_early_dcx, at_args) ;
230230
231- let Some ( matches) = handle_options( & default_early_dcx, & args) else {
232- return ;
231+ let ( matches, help_only) = match handle_options( & default_early_dcx, & args) {
232+ HandledOptions :: None => return ,
233+ HandledOptions :: Normal ( matches) => ( matches, false ) ,
234+ HandledOptions :: HelpOnly ( matches) => ( matches, true ) ,
233235 } ;
234236
235237 let sopts = config:: build_session_options( & mut default_early_dcx, & matches) ;
@@ -291,6 +293,11 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
291293 return early_exit( ) ;
292294 }
293295
296+ // We have now handled all help options, exit
297+ if help_only {
298+ return early_exit( ) ;
299+ }
300+
294301 if print_crate_info( codegen_backend, sess, has_input) == Compilation :: Stop {
295302 return early_exit( ) ;
296303 }
@@ -1097,7 +1104,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
10971104 // Don't handle -W help here, because we might first load additional lints.
10981105 let debug_flags = matches. opt_strs( "Z" ) ;
10991106 if debug_flags. iter( ) . any( |x| * x == "help" ) {
1100- describe_debug_flags ( ) ;
1107+ describe_unstable_flags ( ) ;
11011108 return true ;
11021109 }
11031110
@@ -1137,8 +1144,8 @@ fn get_backend_from_raw_matches(
11371144 get_codegen_backend( early_dcx, & sysroot, backend_name, & target)
11381145}
11391146
1140- fn describe_debug_flags ( ) {
1141- safe_println!( "\n Available options:\n " ) ;
1147+ fn describe_unstable_flags ( ) {
1148+ safe_println!( "\n Available unstable options:\n " ) ;
11421149 print_flag_list( "-Z" , config:: Z_OPTIONS ) ;
11431150}
11441151
@@ -1162,6 +1169,16 @@ fn print_flag_list<T>(cmdline_opt: &str, flag_list: &[OptionDesc<T>]) {
11621169 }
11631170}
11641171
1172+ pub enum HandledOptions {
1173+ /// Parsing failed, or we parsed a flag causing an early exit
1174+ None ,
1175+ /// Successful parsing
1176+ Normal ( getopts:: Matches ) ,
1177+ /// Parsing succeeded, but we received one or more 'help' flags
1178+ /// The compiler should proceed only until a possible `-W help` flag has been processed
1179+ HelpOnly ( getopts:: Matches ) ,
1180+ }
1181+
11651182/// Process command line options. Emits messages as appropriate. If compilation
11661183/// should continue, returns a getopts::Matches object parsed from args,
11671184/// otherwise returns `None`.
@@ -1189,7 +1206,7 @@ fn print_flag_list<T>(cmdline_opt: &str, flag_list: &[OptionDesc<T>]) {
11891206/// This does not need to be `pub` for rustc itself, but @chaosite needs it to
11901207/// be public when using rustc as a library, see
11911208/// <https://github.com/rust-lang/rust/commit/2b4c33817a5aaecabf4c6598d41e190080ec119e>
1192- pub fn handle_options( early_dcx: & EarlyDiagCtxt , args: & [ String ] ) -> Option <getopts :: Matches > {
1209+ pub fn handle_options( early_dcx: & EarlyDiagCtxt , args: & [ String ] ) -> HandledOptions {
11931210 // Parse with *all* options defined in the compiler, we don't worry about
11941211 // option stability here we just want to parse as much as possible.
11951212 let mut options = getopts:: Options :: new( ) ;
@@ -1235,26 +1252,69 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
12351252 // (unstable option being used on stable)
12361253 nightly_options:: check_nightly_options( early_dcx, & matches, & config:: rustc_optgroups( ) ) ;
12371254
1238- if args. is_empty( ) || matches. opt_present( "h" ) || matches. opt_present( "help" ) {
1239- // Only show unstable options in --help if we accept unstable options.
1240- let unstable_enabled = nightly_options:: is_unstable_enabled( & matches) ;
1241- let nightly_build = nightly_options:: match_is_nightly_build( & matches) ;
1242- usage( matches. opt_present( "verbose" ) , unstable_enabled, nightly_build) ;
1243- return None ;
1255+ // Handle the special case of -Wall.
1256+ let wall = matches. opt_strs( "W" ) ;
1257+ if wall. iter( ) . any( |x| * x == "all" ) {
1258+ print_wall_help( ) ;
1259+ return HandledOptions :: None ;
12441260 }
12451261
1246- if describe_flag_categories( early_dcx, & matches) {
1247- return None ;
1262+ if handle_help( & matches, args) {
1263+ return HandledOptions :: HelpOnly ( matches) ;
1264+ }
1265+
1266+ if matches. opt_strs( "C" ) . iter( ) . any( |x| x == "passes=list" ) {
1267+ get_backend_from_raw_matches( early_dcx, & matches) . print_passes( ) ;
1268+ return HandledOptions :: None ;
12481269 }
12491270
12501271 if matches. opt_present( "version" ) {
12511272 version!( early_dcx, "rustc" , & matches) ;
1252- return None ;
1273+ return HandledOptions :: None ;
12531274 }
12541275
12551276 warn_on_confusing_output_filename_flag( early_dcx, & matches, args) ;
12561277
1257- Some ( matches)
1278+ HandledOptions :: Normal ( matches)
1279+ }
1280+
1281+ /// Handle help options in the order they are provided, ignoring other flags. Returns if any options were handled
1282+ /// Handled options:
1283+ /// - `-h`/`--help`/empty arguments
1284+ /// - `-Z help`
1285+ /// - `-C help`
1286+ /// NOTE: `-W help` is NOT handled here, as additional lints may be loaded.
1287+ pub fn handle_help( matches: & getopts:: Matches , args: & [ String ] ) -> bool {
1288+ let opt_pos = |opt| matches. opt_positions( opt) . first( ) . copied( ) ;
1289+ let opt_help_pos = |opt| {
1290+ matches
1291+ . opt_strs_pos( opt)
1292+ . iter( )
1293+ . filter_map( |( pos, oval) | if oval == "help" { Some ( * pos) } else { None } )
1294+ . next( )
1295+ } ;
1296+ let help_pos = if args. is_empty( ) { Some ( 0 ) } else { opt_pos( "h" ) . or_else( || opt_pos( "help" ) ) } ;
1297+ let zhelp_pos = opt_help_pos( "Z" ) ;
1298+ let chelp_pos = opt_help_pos( "C" ) ;
1299+ let print_help = || {
1300+ // Only show unstable options in --help if we accept unstable options.
1301+ let unstable_enabled = nightly_options:: is_unstable_enabled( & matches) ;
1302+ let nightly_build = nightly_options:: match_is_nightly_build( & matches) ;
1303+ usage( matches. opt_present( "verbose" ) , unstable_enabled, nightly_build) ;
1304+ } ;
1305+
1306+ let mut helps = [
1307+ ( help_pos, & print_help as & dyn Fn ( ) ) ,
1308+ ( zhelp_pos, & describe_unstable_flags) ,
1309+ ( chelp_pos, & describe_codegen_flags) ,
1310+ ] ;
1311+ helps. sort_by_key( |( pos, _) | pos. clone( ) ) ;
1312+ let mut printed_any = false ;
1313+ for printer in helps. iter( ) . filter_map( |( pos, func) | pos. is_some( ) . then_some( func) ) {
1314+ printer( ) ;
1315+ printed_any = true ;
1316+ }
1317+ printed_any
12581318}
12591319
12601320/// Warn if `-o` is used without a space between the flag name and the value
0 commit comments