From 9b125b5d9f2e55c8b1ae6f5e037f4617b145310a Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:11:57 +0200 Subject: [PATCH] Stop telling people to submit bugs for internal feature ICEs This keeps track of usage of internal features, and changes the message to instead tell them that using internal features is not supported. See MCP 620. --- compiler/rustc_driver_impl/messages.ftl | 1 + compiler/rustc_driver_impl/src/lib.rs | 66 ++++++++++++++++--- .../src/session_diagnostics.rs | 4 ++ compiler/rustc_expand/src/config.rs | 5 ++ compiler/rustc_interface/src/interface.rs | 7 ++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_interface/src/util.rs | 4 +- compiler/rustc_session/src/session.rs | 9 ++- src/librustdoc/core.rs | 1 + src/librustdoc/doctest.rs | 1 + src/librustdoc/lib.rs | 1 + src/tools/clippy/src/driver.rs | 2 +- src/tools/miri/src/bin/miri.rs | 4 +- src/tools/rustfmt/src/bin/main.rs | 2 +- 14 files changed, 93 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl index d3bd3244a52aa..dd651561f6beb 100644 --- a/compiler/rustc_driver_impl/messages.ftl +++ b/compiler/rustc_driver_impl/messages.ftl @@ -1,5 +1,6 @@ driver_impl_ice = the compiler unexpectedly panicked. this is a bug. driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} +driver_impl_ice_bug_report_internal_feature = using internal features is not supported and is expected to lead to internal compiler errors driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden driver_impl_ice_flags = compiler flags: {$flags} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5bb7c41677cd1..0d821b792007a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -60,7 +60,7 @@ use std::path::PathBuf; use std::process::{self, Command, Stdio}; use std::str; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::OnceLock; +use std::sync::{Arc, OnceLock}; use std::time::{Instant, SystemTime}; use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; @@ -224,11 +224,18 @@ pub struct RunCompiler<'a, 'b> { file_loader: Option>, make_codegen_backend: Option Box + Send>>, + using_internal_features: Option>, } impl<'a, 'b> RunCompiler<'a, 'b> { pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self { - Self { at_args, callbacks, file_loader: None, make_codegen_backend: None } + Self { + at_args, + callbacks, + file_loader: None, + make_codegen_backend: None, + using_internal_features: None, + } } /// Set a custom codegen backend. @@ -260,9 +267,25 @@ impl<'a, 'b> RunCompiler<'a, 'b> { self } + /// Set the session-global flag that checks whether internal features have been used, + /// suppressing the message about submitting an issue in ICEs when enabled. + pub fn set_using_internal_features( + &mut self, + using_internal_features: Option>, + ) -> &mut Self { + self.using_internal_features = using_internal_features; + self + } + /// Parse args and run the compiler. pub fn run(self) -> interface::Result<()> { - run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend) + run_compiler( + self.at_args, + self.callbacks, + self.file_loader, + self.make_codegen_backend, + self.using_internal_features, + ) } } @@ -273,6 +296,7 @@ fn run_compiler( make_codegen_backend: Option< Box Box + Send>, >, + using_internal_features: Option>, ) -> interface::Result<()> { let mut early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); @@ -316,6 +340,7 @@ fn run_compiler( override_queries: None, make_codegen_backend, registry: diagnostics_registry(), + using_internal_features, expanded_args: args, }; @@ -1323,8 +1348,16 @@ fn ice_path() -> &'static Option { /// If you have no extra info to report, pass the empty closure `|_| ()` as the argument to /// extra_info. /// +/// If emitting the "please submit a bug" message is fine when internal features are enabled, `None` +/// can be passed as the `using_internal_features`. To hide the note, pass in a bool that is also passed +/// to [`RunCompiler::set_using_internal_features`]. +/// /// A custom rustc driver can skip calling this to set up a custom ICE hook. -pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) { +pub fn install_ice_hook( + bug_report_url: &'static str, + extra_info: fn(&Handler), + using_internal_features: Option>, +) { // If the user has not explicitly overridden "RUST_BACKTRACE", then produce // full backtraces. When a compiler ICE happens, we want to gather // as much information as possible to present in the issue opened @@ -1384,7 +1417,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) } // Print the ICE message - report_ice(info, bug_report_url, extra_info); + report_ice(info, bug_report_url, extra_info, using_internal_features.clone()); }, )); } @@ -1395,7 +1428,12 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. -fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: fn(&Handler)) { +fn report_ice( + info: &panic::PanicInfo<'_>, + bug_report_url: &str, + extra_info: fn(&Handler), + using_internal_features: Option>, +) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( @@ -1412,7 +1450,13 @@ fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: fn( handler.emit_err(session_diagnostics::Ice); } - handler.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + if using_internal_features + .map_or(false, |internal| internal.load(std::sync::atomic::Ordering::Relaxed)) + { + handler.emit_note(session_diagnostics::IceBugReportInternalFeature); + } else { + handler.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + } let version = util::version_str!().unwrap_or("unknown_version"); let triple = config::host_triple(); @@ -1493,10 +1537,12 @@ pub fn main() -> ! { let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let using_internal_features = Some(Arc::default()); + init_rustc_env_logger(&handler); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); - install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); + install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| (), using_internal_features.clone()); let exit_code = catch_with_exit_code(|| { let args = env::args_os() .enumerate() @@ -1506,7 +1552,9 @@ pub fn main() -> ! { }) }) .collect::>(); - RunCompiler::new(&args, &mut callbacks).run() + let mut run = RunCompiler::new(&args, &mut callbacks); + run.set_using_internal_features(using_internal_features); + run.run() }); if let Some(format) = callbacks.time_passes { diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 442989f8de83a..2b31fdd77cca3 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -42,6 +42,10 @@ pub(crate) struct IceBugReport<'a> { pub bug_report_url: &'a str, } +#[derive(Diagnostic)] +#[diag(driver_impl_ice_bug_report_internal_feature)] +pub(crate) struct IceBugReportInternalFeature; + #[derive(Diagnostic)] #[diag(driver_impl_ice_version)] pub(crate) struct IceVersion<'a> { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index b73c7593381c3..7782f2a2bb1b5 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -167,6 +167,11 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features { // If the declared feature is unstable, record it. if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) { (f.set_enabled)(&mut features); + if features.internal(name) { + if let Some(using_internal_features) = &sess.using_internal_features { + using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed); + } + } features.set_declared_lang_feature(name, mi.span(), None); continue; } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1c330c064ab69..743850e9e6360 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -23,6 +23,7 @@ use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use std::path::PathBuf; use std::result; +use std::sync::Arc; pub type Result = result::Result; @@ -280,6 +281,11 @@ pub struct Config { /// Registry of diagnostics codes. pub registry: Registry, + /// Enabled when a feature marked as `internal` is enabled. Makes it so that + /// "please report a bug" is hidden, as ICEs with internal features are wontfix, + /// and they are usually the cause of the ICEs. + pub using_internal_features: Option>, + /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows /// This is mainly useful for other tools that reads that debuginfo to figure out @@ -323,6 +329,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.make_codegen_backend, registry.clone(), config.ice_file, + config.using_internal_features, config.expanded_args, ); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7799af370089a..38edf0b3b2d17 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -69,6 +69,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se None, "", None, + None, Default::default(), ); (sess, cfg) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0634e44c5620b..647e739cd84a4 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -26,7 +26,7 @@ use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::OnceLock; +use std::sync::{Arc, OnceLock}; use std::thread; /// Function pointer type that constructs a new CodegenBackend. @@ -71,6 +71,7 @@ pub fn create_session( >, descriptions: Registry, ice_file: Option, + using_internal_features: Option>, expanded_args: Vec, ) -> (Session, Box) { let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { @@ -114,6 +115,7 @@ pub fn create_session( target_override, rustc_version_str().unwrap_or("unknown"), ice_file, + using_internal_features, expanded_args, ); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5cac11cc8f782..6feece75d0959 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -44,7 +44,7 @@ use std::fmt; use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::sync::Arc; +use std::sync::{atomic::AtomicBool, Arc}; use std::time::Duration; pub struct OptimizationFuel { @@ -201,6 +201,11 @@ pub struct Session { /// The version of the rustc process, possibly including a commit hash and description. pub cfg_version: &'static str, + /// Enabled when a feature marked as `internal` is enabled. Makes it so that + /// "please report a bug" is hidden, as ICEs with internal features are wontfix, + /// and they are usually the cause of the ICEs. + pub using_internal_features: Option>, + /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows /// This is mainly useful for other tools that reads that debuginfo to figure out @@ -1333,6 +1338,7 @@ pub fn build_session( target_override: Option, cfg_version: &'static str, ice_file: Option, + using_internal_features: Option>, expanded_args: Vec, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override @@ -1469,6 +1475,7 @@ pub fn build_session( target_features: Default::default(), unstable_target_features: Default::default(), cfg_version, + using_internal_features, expanded_args, }; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3e6066c78fba2..7b8e675a36972 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -292,6 +292,7 @@ pub(crate) fn create_config( make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, + using_internal_features: None, expanded_args, } } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 741d329fb1922..e3d7e6af1e5aa 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -109,6 +109,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, + using_internal_features: None, expanded_args: options.expanded_args.clone(), }; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 67f5ea5d98b2a..a2008dd85e70b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -161,6 +161,7 @@ pub fn main() { "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md", |_| (), + None, ); // When using CI artifacts with `download-rustc`, tracing is unconditionally built diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index d47767faed9ed..94a4d3f71f949 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -184,7 +184,7 @@ pub fn main() { // accept a generic closure. let version_info = rustc_tools_util::get_version_info!(); handler.note_without_error(format!("Clippy version: {version_info}")); - }); + }, None); exit(rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec = env::args().collect(); diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index fc6151772a0fd..c8ddf72cd2161 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -295,7 +295,7 @@ fn main() { // If the environment asks us to actually be rustc, then do that. if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. - rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); + rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| (), None); rustc_driver::init_rustc_env_logger(&handler); let target_crate = if crate_kind == "target" { @@ -315,7 +315,7 @@ fn main() { } // Add an ICE bug report hook. - rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); + rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| (), None); // Init loggers the Miri way. init_early_loggers(&handler); diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 03b75c1b0410d..f07e67e6ac68e 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -27,7 +27,7 @@ const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?la extern crate rustc_driver; fn main() { - rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| ()); + rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| (), None); env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = make_opts();