From 618409901ac354b57e6f3ea9fdbd6c4e88a10ef9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 5 Dec 2023 12:47:12 +1100 Subject: [PATCH] Fewer early errors. `build_session` is passed an `EarlyErrorHandler` and then constructs a `Handler`. But the `EarlyErrorHandler` is still used for some time after that. This commit changes `build_session` so it consumes the passed `EarlyErrorHandler`, and also drops it as soon as the `Handler` is built. As a result, `parse_cfg` and `parse_check_cfg` now take a `Handler` instead of an `EarlyErrorHandler`. --- compiler/rustc_interface/src/interface.rs | 40 +++++++++++-------- compiler/rustc_interface/src/tests.rs | 8 ++-- compiler/rustc_session/messages.ftl | 3 ++ compiler/rustc_session/src/errors.rs | 6 +++ compiler/rustc_session/src/session.rs | 37 ++++++++--------- .../jobserver-error/cannot_open_fd.stderr | 2 + .../jobserver-error/not_a_pipe.stderr | 2 + 7 files changed, 60 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8a6d8d3d42e..fefff03830f 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -42,7 +42,7 @@ pub struct Compiler { } /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. -pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { +pub(crate) fn parse_cfg(handler: &Handler, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( @@ -52,10 +52,14 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { macro_rules! error { ($reason: expr) => { - handler.early_error(format!( - concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), - s - )); + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + handler + .struct_fatal(format!( + concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), + s + )) + .emit(); }; } @@ -97,7 +101,7 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { } /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { +pub(crate) fn parse_check_cfg(handler: &Handler, specs: Vec) -> CheckCfg { // If any --check-cfg is passed then exhaustive_values and exhaustive_names // are enabled by default. let exhaustive_names = !specs.is_empty(); @@ -113,10 +117,14 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) - macro_rules! error { ($reason:expr) => { - handler.early_error(format!( - concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), - s - )) + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + handler + .struct_fatal(format!( + concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), + s + )) + .emit() }; } @@ -388,13 +396,13 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se || { crate::callbacks::setup_callbacks(); - let handler = EarlyErrorHandler::new(config.opts.error_format); + let early_handler = EarlyErrorHandler::new(config.opts.error_format); let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend { make_codegen_backend(&config.opts) } else { util::get_codegen_backend( - &handler, + &early_handler, &config.opts.maybe_sysroot, config.opts.unstable_opts.codegen_backend.as_deref(), ) @@ -411,7 +419,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se ) { Ok(bundle) => bundle, Err(e) => { - handler.early_error(format!("failed to load fluent bundle: {e}")); + early_handler.early_error(format!("failed to load fluent bundle: {e}")); } }; @@ -422,7 +430,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let target_override = codegen_backend.target_override(&config.opts); let mut sess = rustc_session::build_session( - &handler, + early_handler, config.opts, CompilerIO { input: config.input, @@ -444,12 +452,12 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se codegen_backend.init(&sess); - let cfg = parse_cfg(&handler, config.crate_cfg); + let cfg = parse_cfg(&sess.diagnostic(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.parse_sess.config = cfg; - let mut check_cfg = parse_check_cfg(&handler, config.crate_check_cfg); + let mut check_cfg = parse_check_cfg(&sess.diagnostic(), config.crate_check_cfg); check_cfg.fill_well_known(&sess.target); sess.parse_sess.check_config = check_cfg; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f65e37d11e8..f7b6ab331a5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -26,10 +26,9 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let mut early_handler = EarlyErrorHandler::new(ErrorOutputType::default()); let registry = registry::Registry::new(&[]); - let sessopts = build_session_options(&mut handler, &matches); - let cfg = parse_cfg(&handler, matches.opt_strs("cfg")); + let sessopts = build_session_options(&mut early_handler, &matches); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -38,7 +37,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { temps_dir, }; let sess = build_session( - &handler, + early_handler, sessopts, io, None, @@ -52,6 +51,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { Arc::default(), Default::default(), ); + let cfg = parse_cfg(&sess.diagnostic(), matches.opt_strs("cfg")); (sess, cfg) } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 3a7959c332e..f2e646c70f5 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -16,6 +16,8 @@ session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has session_expr_parentheses_needed = parentheses are required to parse this as an expression +session_failed_to_create_profiler = failed to create profiler: {$err} + session_feature_diagnostic_for_issue = see issue #{$n} for more information @@ -73,6 +75,7 @@ session_not_supported = not supported session_nul_in_c_str = null characters in C string literals are not supported session_octal_float_literal_not_supported = octal float literal is not supported + session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist. diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 70ee46ea902..8a9315dde51 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -444,3 +444,9 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664; #[derive(Diagnostic)] #[diag(session_function_return_thunk_extern_requires_non_large_code_model)] pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; + +#[derive(Diagnostic)] +#[diag(session_failed_to_create_profiler)] +pub struct FailedToCreateProfiler { + pub err: String, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 57a535d8c10..09a6a585d9c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -24,7 +24,7 @@ use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, FluentBundle, Handler, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted, - SubdiagnosticMessage, TerminalUrl, + TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -1349,7 +1349,7 @@ fn default_emitter( // JUSTIFICATION: literally session construction #[allow(rustc::bad_opt_access)] pub fn build_session( - handler: &EarlyErrorHandler, + early_handler: EarlyErrorHandler, sopts: config::Options, io: CompilerIO, bundle: Option>, @@ -1379,12 +1379,13 @@ pub fn build_session( None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), }; - let target_cfg = config::build_target_config(handler, &sopts, target_override, &sysroot); + let target_cfg = config::build_target_config(&early_handler, &sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); - let (host, target_warnings) = Target::search(&host_triple, &sysroot) - .unwrap_or_else(|e| handler.early_error(format!("Error loading host specification: {e}"))); + let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { + early_handler.early_error(format!("Error loading host specification: {e}")) + }); for warning in target_warnings.warning_messages() { - handler.early_warn(warning) + early_handler.early_warn(warning) } let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); @@ -1413,6 +1414,10 @@ pub fn build_session( span_diagnostic = span_diagnostic.with_ice_file(ice_file); } + // Now that the proper handler has been constructed, drop the early handler + // to prevent accidental use. + drop(early_handler); + let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile { let directory = @@ -1427,7 +1432,7 @@ pub fn build_session( match profiler { Ok(profiler) => Some(Arc::new(profiler)), Err(e) => { - handler.early_warn(format!("failed to create profiler: {e}")); + span_diagnostic.emit_warning(errors::FailedToCreateProfiler { err: e.to_string() }); None } } @@ -1471,7 +1476,13 @@ pub fn build_session( // Check jobserver before getting `jobserver::client`. jobserver::check(|err| { - handler.early_warn_with_note(err, "the build environment is likely misconfigured") + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + parse_sess + .span_diagnostic + .struct_warn(err) + .note("the build environment is likely misconfigured") + .emit() }); let sess = Session { @@ -1781,16 +1792,6 @@ impl EarlyErrorHandler { pub fn early_warn(&self, msg: impl Into) { self.handler.struct_warn(msg).emit() } - - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - pub fn early_warn_with_note( - &self, - msg: impl Into, - note: impl Into, - ) { - self.handler.struct_warn(msg).note(note).emit() - } } fn mk_emitter(output: ErrorOutputType) -> Box { diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr index 343de5cd52c..a2f77a94e4f 100644 --- a/tests/run-make/jobserver-error/cannot_open_fd.stderr +++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr @@ -4,3 +4,5 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="-- error: no input filename given +warning: 1 warning emitted + diff --git a/tests/run-make/jobserver-error/not_a_pipe.stderr b/tests/run-make/jobserver-error/not_a_pipe.stderr index 536c04576b9..9158fda6e47 100644 --- a/tests/run-make/jobserver-error/not_a_pipe.stderr +++ b/tests/run-make/jobserver-error/not_a_pipe.stderr @@ -2,3 +2,5 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="-- | = note: the build environment is likely misconfigured +warning: 1 warning emitted +