diff options
| author | 许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com> | 2023-06-23 05:56:09 +0800 | 
|---|---|---|
| committer | 许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com> | 2023-06-27 23:23:33 +0800 | 
| commit | cef812bd958d5037224aebe3721f3ffc9c80965e (patch) | |
| tree | 19351f8407da440738b59892da7c9309b97bb82a /compiler/rustc_driver_impl/src/lib.rs | |
| parent | f42f19b6d3d785a74dbe57aa395b6c288437dd51 (diff) | |
| download | rust-cef812bd958d5037224aebe3721f3ffc9c80965e.tar.gz rust-cef812bd958d5037224aebe3721f3ffc9c80965e.zip | |
Provide more context for `rustc +nightly -Zunstable-options` on stable
Diffstat (limited to 'compiler/rustc_driver_impl/src/lib.rs')
| -rw-r--r-- | compiler/rustc_driver_impl/src/lib.rs | 128 | 
1 files changed, 72 insertions, 56 deletions
| diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 984cc1557a4..4b4573ec2eb 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -40,8 +40,7 @@ use rustc_session::config::{ use rustc_session::cstore::MetadataLoader; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; -use rustc_session::{config, Session}; -use rustc_session::{early_error, early_error_no_abort, early_warn}; +use rustc_session::{config, EarlyErrorHandler, Session}; use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use rustc_target::json::ToJson; @@ -174,6 +173,7 @@ pub trait Callbacks { /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_analysis<'tcx>( &mut self, + _handler: &EarlyErrorHandler, _compiler: &interface::Compiler, _queries: &'tcx Queries<'tcx>, ) -> Compilation { @@ -260,6 +260,8 @@ fn run_compiler( Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>, >, ) -> interface::Result<()> { + let mut early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -270,22 +272,22 @@ fn run_compiler( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = args::arg_expand_all(at_args); + let args = args::arg_expand_all(&early_error_handler, at_args); - let Some(matches) = handle_options(&args) else { return Ok(()) }; + let Some(matches) = handle_options(&early_error_handler, &args) else { return Ok(()) }; - let sopts = config::build_session_options(&matches); + let sopts = config::build_session_options(&mut early_error_handler, &matches); // Set parallel mode before thread pool creation, which will create `Lock`s. interface::set_thread_safe_mode(&sopts.unstable_opts); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(diagnostics_registry(), code, sopts.error_format); + handle_explain(&early_error_handler, diagnostics_registry(), code); return Ok(()); } - let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg")); - let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg")); + let cfg = interface::parse_cfgspecs(&early_error_handler, matches.opt_strs("cfg")); + let check_cfg = interface::parse_check_cfg(&early_error_handler, matches.opt_strs("check-cfg")); let (odir, ofile) = make_output(&matches); let mut config = interface::Config { opts: sopts, @@ -304,7 +306,7 @@ fn run_compiler( registry: diagnostics_registry(), }; - match make_input(config.opts.error_format, &matches.free) { + match make_input(&early_error_handler, &matches.free) { Err(reported) => return Err(reported), Ok(Some(input)) => { config.input = input; @@ -314,8 +316,13 @@ fn run_compiler( Ok(None) => match matches.free.len() { 0 => { callbacks.config(&mut config); + + early_error_handler.abort_if_errors(); + interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; + let handler = EarlyErrorHandler::new(sopts.error_format); + if sopts.describe_lints { let mut lint_store = rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); @@ -329,31 +336,38 @@ fn run_compiler( describe_lints(compiler.session(), &lint_store, registered_lints); return; } - let should_stop = - print_crate_info(&**compiler.codegen_backend(), compiler.session(), false); + let should_stop = print_crate_info( + &handler, + &**compiler.codegen_backend(), + compiler.session(), + false, + ); if should_stop == Compilation::Stop { return; } - early_error(sopts.error_format, "no input filename given") + handler.early_error("no input filename given") }); return Ok(()); } 1 => panic!("make_input should have provided valid inputs"), - _ => early_error( - config.opts.error_format, - format!( - "multiple input filenames provided (first two filenames are `{}` and `{}`)", - matches.free[0], matches.free[1], - ), - ), + _ => early_error_handler.early_error(format!( + "multiple input filenames provided (first two filenames are `{}` and `{}`)", + matches.free[0], matches.free[1], + )), }, }; + early_error_handler.abort_if_errors(); + interface::run_compiler(config, |compiler| { let sess = compiler.session(); - let should_stop = print_crate_info(&**compiler.codegen_backend(), sess, true) - .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader())) + let handler = EarlyErrorHandler::new(sess.opts.error_format); + + let should_stop = print_crate_info(&handler, &**compiler.codegen_backend(), sess, true) + .and_then(|| { + list_metadata(&handler, sess, &*compiler.codegen_backend().metadata_loader()) + }) .and_then(|| try_process_rlink(sess, compiler)); if should_stop == Compilation::Stop { @@ -421,7 +435,7 @@ fn run_compiler( queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?; - if callbacks.after_analysis(compiler, queries) == Compilation::Stop { + if callbacks.after_analysis(&handler, compiler, queries) == Compilation::Stop { return early_exit(); } @@ -475,7 +489,7 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileNa // Extract input (string or file and optional path) from matches. fn make_input( - error_format: ErrorOutputType, + handler: &EarlyErrorHandler, free_matches: &[String], ) -> Result<Option<Input>, ErrorGuaranteed> { if free_matches.len() == 1 { @@ -485,8 +499,7 @@ fn make_input( if io::stdin().read_to_string(&mut src).is_err() { // Immediately stop compilation if there was an issue reading // the input (for example if the input stream is not UTF-8). - let reported = early_error_no_abort( - error_format, + let reported = handler.early_error_no_abort( "couldn't read from stdin, as it did not contain valid UTF-8", ); return Err(reported); @@ -527,7 +540,7 @@ impl Compilation { } } -fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { +fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; @@ -557,7 +570,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { } } Err(InvalidErrorCode) => { - early_error(output, format!("{code} is not a valid error code")); + handler.early_error(format!("{code} is not a valid error code")); } } } @@ -636,7 +649,11 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp } } -pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation { +pub fn list_metadata( + handler: &EarlyErrorHandler, + sess: &Session, + metadata_loader: &dyn MetadataLoader, +) -> Compilation { if sess.opts.unstable_opts.ls { match sess.io.input { Input::File(ref ifile) => { @@ -646,7 +663,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { - early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); + handler.early_error("cannot list metadata for stdin"); } } return Compilation::Stop; @@ -656,6 +673,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co } fn print_crate_info( + handler: &EarlyErrorHandler, codegen_backend: &dyn CodegenBackend, sess: &Session, parse_attrs: bool, @@ -787,10 +805,8 @@ fn print_crate_info( .expect("unknown Apple target OS") ) } else { - early_error( - ErrorOutputType::default(), - "only Apple targets currently support deployment version info", - ) + handler + .early_error("only Apple targets currently support deployment version info") } } } @@ -801,11 +817,12 @@ fn print_crate_info( /// Prints version information /// /// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate. -pub macro version($binary: literal, $matches: expr) { +pub macro version($handler: expr, $binary: literal, $matches: expr) { fn unw(x: Option<&str>) -> &str { x.unwrap_or("unknown") } $crate::version_at_macro_invocation( + $handler, $binary, $matches, unw(option_env!("CFG_VERSION")), @@ -817,6 +834,7 @@ pub macro version($binary: literal, $matches: expr) { #[doc(hidden)] // use the macro instead pub fn version_at_macro_invocation( + handler: &EarlyErrorHandler, binary: &str, matches: &getopts::Matches, version: &str, @@ -837,7 +855,7 @@ pub fn version_at_macro_invocation( let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(&None, backend_name).print_version(); + get_codegen_backend(handler, &None, backend_name).print_version(); } } @@ -1014,7 +1032,7 @@ Available lint options: /// Show help for flag categories shared between rustdoc and rustc. /// /// Returns whether a help option was printed. -pub fn describe_flag_categories(matches: &Matches) -> bool { +pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches) -> bool { // Handle the special case of -Wall. let wall = matches.opt_strs("W"); if wall.iter().any(|x| *x == "all") { @@ -1036,15 +1054,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } if cg_flags.iter().any(|x| *x == "no-stack-check") { - early_warn( - ErrorOutputType::default(), - "the --no-stack-check flag is deprecated and does nothing", - ); + handler.early_warn("the --no-stack-check flag is deprecated and does nothing"); } if cg_flags.iter().any(|x| *x == "passes=list") { let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(&None, backend_name).print_passes(); + get_codegen_backend(handler, &None, backend_name).print_passes(); return true; } @@ -1101,7 +1116,7 @@ fn print_flag_list<T>( /// /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. -pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { +pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option<getopts::Matches> { if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. @@ -1127,7 +1142,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")), _ => None, }; - early_error(ErrorOutputType::default(), msg.unwrap_or_else(|| e.to_string())); + handler.early_error(msg.unwrap_or_else(|| e.to_string())); }); // For all options we just parsed, we check a few aspects: @@ -1141,7 +1156,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { // we're good to go. // * Otherwise, if we're an unstable option then we generate an error // (unstable option being used on stable) - nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); + nightly_options::check_nightly_options(handler, &matches, &config::rustc_optgroups()); if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. @@ -1151,12 +1166,12 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { return None; } - if describe_flag_categories(&matches) { + if describe_flag_categories(handler, &matches) { return None; } if matches.opt_present("version") { - version!("rustc", &matches); + version!(handler, "rustc", &matches); return None; } @@ -1276,7 +1291,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) if let Some(msg) = info.payload().downcast_ref::<String>() { if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") { // the error code is already going to be reported when the panic unwinds up the stack - let _ = early_error_no_abort(ErrorOutputType::default(), msg.clone()); + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let _ = handler.early_error_no_abort(msg.clone()); return; } }; @@ -1359,16 +1375,16 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. -pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG"); +pub fn init_rustc_env_logger(handler: &EarlyErrorHandler) { + init_env_logger(handler, "RUSTC_LOG"); } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. -pub fn init_env_logger(env: &str) { +pub fn init_env_logger(handler: &EarlyErrorHandler, env: &str) { if let Err(error) = rustc_log::init_env_logger(env) { - early_error(ErrorOutputType::default(), error.to_string()); + handler.early_error(error.to_string()); } } @@ -1424,7 +1440,10 @@ mod signal_handler { pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); - init_rustc_env_logger(); + + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + + init_rustc_env_logger(&handler); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); @@ -1433,10 +1452,7 @@ pub fn main() -> ! { .enumerate() .map(|(i, arg)| { arg.into_string().unwrap_or_else(|arg| { - early_error( - ErrorOutputType::default(), - format!("argument {i} is not valid Unicode: {arg:?}"), - ) + handler.early_error(format!("argument {i} is not valid Unicode: {arg:?}")) }) }) .collect::<Vec<_>>(); | 
