From 700ba81e90e7b56ba08ad9f4212283bc6502d7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 10 Jan 2023 17:29:02 +0000 Subject: [PATCH 1/6] Teach `rustc` to write the backtrace and query stack to disk. * On non-`-dev` builds, always hide the backtrace and query stack. * Introduce `RUSTC_BACKTRACE_FORCE` where `1` will always print the backtrace and `0` will always hide it. --- Cargo.lock | 4 + compiler/rustc_driver/Cargo.toml | 6 +- compiler/rustc_driver/src/lib.rs | 171 +++++++++++++++--- tests/ui/impl-trait/issues/issue-86800.stderr | 4 +- tests/ui/layout/valid_range_oob.stderr | 2 +- tests/ui/panics/default-backtrace-ice.stderr | 4 +- .../ui/treat-err-as-bug/delay_span_bug.stderr | 2 +- tests/ui/treat-err-as-bug/err.stderr | 2 +- 8 files changed, 159 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4bea3af7f3bfa..8d1079135c0d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3915,6 +3915,7 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ + "backtrace", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3934,11 +3935,14 @@ dependencies = [ "rustc_middle", "rustc_parse", "rustc_plugin_impl", + "rustc_query_impl", + "rustc_query_system", "rustc_save_analysis", "rustc_session", "rustc_span", "rustc_target", "serde_json", + "time 0.3.17", "tracing", "winapi", ] diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 59e937777483e..7bf3f8d860930 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -7,8 +7,10 @@ edition = "2021" crate-type = ["dylib"] [dependencies] -tracing = { version = "0.1.35" } +backtrace = "0.3.66" serde_json = "1.0.59" +time = { version = "0.3.17", features = ["std", "formatting"] } +tracing = { version = "0.1.35" } rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } @@ -30,6 +32,8 @@ rustc_error_codes = { path = "../rustc_error_codes" } rustc_interface = { path = "../rustc_interface" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } +rustc_query_system = { path = "../rustc_query_system" } +rustc_query_impl = { path = "../rustc_query_impl" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } [target.'cfg(unix)'.dependencies] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 16f64235562f1..3a49488544796 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -8,6 +8,7 @@ #![feature(is_terminal)] #![feature(once_cell)] #![feature(decl_macro)] +#![feature(panic_info_message)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -30,6 +31,8 @@ use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; use rustc_metadata::locator; +use rustc_query_impl::QueryCtxt; +use rustc_query_system::query::QueryContext; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; @@ -45,7 +48,6 @@ use rustc_target::json::ToJson; use std::borrow::Cow; use std::cmp::max; -use std::env; use std::ffi::OsString; use std::fs; use std::io::{self, IsTerminal, Read, Write}; @@ -55,6 +57,7 @@ use std::process::{self, Command, Stdio}; use std::str; use std::sync::LazyLock; use std::time::Instant; +use std::{backtrace, env}; pub mod args; pub mod pretty; @@ -1181,6 +1184,102 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { } } +struct IceError; +impl From for IceError { + fn from(_: time::error::InvalidFormatDescription) -> IceError { + IceError + } +} +impl From for IceError { + fn from(_: time::error::Format) -> IceError { + IceError + } +} +impl From for IceError { + fn from(_: std::io::Error) -> IceError { + IceError + } +} + +fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { + let capture = backtrace::Backtrace::force_capture(); + let now = time::OffsetDateTime::now_utc(); + let format = time::format_description::parse("[year]-[month]-[day]_[hour]:[minute]:[second]")?; + let file_now = now.format(&format)?; + let format = time::format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]")?; + let now = now.format(&format)?; + let path = format!("rustc-ice-context-{file_now}.txt"); + let mut file = std::fs::File::create(&path)?; + writeln!( + file, + "rustc {}{} running on {} at {now}", + util::version_str!().unwrap_or("unknown_version"), + match (option_env!("CFG_VER_HASH"), option_env!("CFG_VER_DATE")) { + (Some(hash), Some(date)) => format!(" ({hash} - {date})"), + (Some(val), None) | (None, Some(val)) => format!(" ({val})"), + (None, None) => String::new(), + }, + config::host_triple(), + )?; + + if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + writeln!(file, "compiler flags:")?; + for flag in flags { + writeln!(file, " {flag}")?; + } + if excluded_cargo_defaults { + writeln!(file, "some of the compiler flags provided by cargo are hidden")?; + } + } + writeln!(file, "")?; + match (info.message(), info.location()) { + (Some(message), Some(location)) => { + writeln!(file, "panicked at {location}:\n{message}")?; + } + (None, Some(location)) => { + writeln!(file, "panicked at {location}")?; + } + (Some(message), None) => { + writeln!(file, "panicked\n{message}")?; + } + (None, None) => { + writeln!(file, "panicked")?; + } + } + + writeln!(file, "")?; + writeln!(file, "{}", capture)?; + + // Be careful relying on global state here: this code is called from + // a panic hook, which means that the global `Handler` may be in a weird + // state if it was responsible for triggering the panic. + // This the same as `interface::try_print_query_stack` but writing to file. + rustc_middle::ty::tls::with_context_opt(|icx| { + let Some(icx) = icx else { return Err(IceError); }; + let qcx = QueryCtxt::from_tcx(icx.tcx); + let query_map = qcx.try_collect_active_jobs(); + let mut i = 0; + let mut current_query = icx.query; + writeln!(file, "")?; + writeln!(file, "query stack during panic:")?; + while let Some(query) = current_query { + let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else { + break; + }; + writeln!( + file, + "#{} [{:?}] {}", + i, query_info.query.dep_kind, query_info.query.description + )?; + current_query = query_info.job.parent; + i += 1; + } + writeln!(file, "end of query stack")?; + Ok(()) + })?; + Ok(path) +} + static DEFAULT_HOOK: LazyLock) + Sync + Send + 'static>> = LazyLock::new(|| { let hook = panic::take_hook(); @@ -1196,9 +1295,17 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + } }; + let is_dev = util::version_str!().map_or_else( + || std::env::var("RUSTC_BACKTRACE_FORCE").as_deref() != Ok("1"), + |v| { + v.ends_with("-dev") + && std::env::var("RUSTC_BACKTRACE_FORCE").as_deref() != Ok("0") + }, + ); + let written_ice = if !is_dev { write_ice_to_disk(info) } else { Err(IceError) }; // Invoke the default handler, which prints the actual panic message and optionally a backtrace // Don't do this for delayed bugs, which already emit their own more useful backtrace. - if !info.payload().is::() { + if !info.payload().is::() && written_ice.is_err() { (*DEFAULT_HOOK)(info); // Separate the output with an empty line @@ -1206,7 +1313,7 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + } // Print the ICE message - report_ice(info, BUG_REPORT_URL); + report_ice(info, BUG_REPORT_URL, written_ice.ok()); })); hook }); @@ -1217,7 +1324,7 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. -pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { +pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ice: Option) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( @@ -1238,39 +1345,51 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { if !info.payload().is::() && !info.payload().is::() { - let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); + let mut d = rustc_errors::Diagnostic::new( + rustc_errors::Level::Bug, + "the compiler unexpectedly panicked. this is a bug.", + ); handler.emit_diagnostic(&mut d); } - let mut xs: Vec> = vec![ - "the compiler unexpectedly panicked. this is a bug.".into(), - format!("we would appreciate a bug report: {bug_report_url}").into(), - format!( - "rustc {} running on {}", - util::version_str!().unwrap_or("unknown_version"), - config::host_triple() - ) - .into(), - ]; - - if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { - xs.push(format!("compiler flags: {}", flags.join(" ")).into()); - - if excluded_cargo_defaults { - xs.push("some of the compiler flags provided by cargo are hidden".into()); + let xs: Vec> = if let Some(path) = &reported_ice { + vec![ + format!("all necessary context about this bug was written to `{path}`").into(), + format!("we would appreciate a bug report with this context at <{bug_report_url}>") + .into(), + ] + } else { + let mut xs = vec![ + format!("we would appreciate a bug report at <{bug_report_url}>").into(), + format!( + "rustc {} running on {}", + util::version_str!().unwrap_or("unknown_version"), + config::host_triple() + ) + .into(), + ]; + if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + xs.push(format!("compiler flags: {}", flags.join(" ")).into()); + + if excluded_cargo_defaults { + xs.push("some of the compiler flags provided by cargo are hidden".into()); + } } - } + xs + }; for note in &xs { handler.note_without_error(note.as_ref()); } - // If backtraces are enabled, also print the query stack - let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0"); + if reported_ice.is_none() { + // If backtraces are enabled, also print the query stack + let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0"); - let num_frames = if backtrace { None } else { Some(2) }; + let num_frames = if backtrace { None } else { Some(2) }; - interface::try_print_query_stack(&handler, num_frames); + interface::try_print_query_stack(&handler, num_frames); + } #[cfg(windows)] unsafe { diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index 6c4aa35679d5b..581630118df5a 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -9,9 +9,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future Date: Wed, 11 Jan 2023 17:11:53 +0000 Subject: [PATCH 2/6] Fix test --- tests/ui/chalkify/bugs/async.rs | 3 +- tests/ui/chalkify/bugs/async.stderr | 44 ++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs index 86ce42631b432..203a59430ffd4 100644 --- a/tests/ui/chalkify/bugs/async.rs +++ b/tests/ui/chalkify/bugs/async.rs @@ -6,7 +6,8 @@ // failure-status:101 // normalize-stderr-test "note: .*" -> "" // normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " .*\n" -> "" +// normalize-stderr-test " ? ?\d\d?\d?:.*\n" -> "" +// normalize-stderr-test " .*\n" -> "" // normalize-stderr-test "DefId([^)]*)" -> "..." fn main() -> () {} diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr index 7e2466dece438..dc296c645b54e 100644 --- a/tests/ui/chalkify/bugs/async.stderr +++ b/tests/ui/chalkify/bugs/async.stderr @@ -1,17 +1,37 @@ -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future -LL |LL | |LL | | } - - -error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:14:29: 16:2] as Future>::Output` cannot be known at compilation time -LL |LL | |LL | | } - - -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future +error[E0277]: `[async fn body@$DIR/async.rs:15:29: --> $DIR/async.rs:15:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________- +LL | | x +LL | | } + | | ^ + | | | + | |_`[async fn body@$DIR/async.rs:15:29: | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:15:29: = + + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:15:29: --> $DIR/async.rs:15:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:15:29: + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: `[async fn body@$DIR/async.rs:15:29: --> $DIR/async.rs:15:25 + | LL | async fn foo(x: u32) -> u32 { + | = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:15:29: = -error: internal compiler error: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:1114:25: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:14:29: 16:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)` +error: internal compiler error: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:1114:25: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:15:29: --> $DIR/async.rs:15:25 + | LL | async fn foo(x: u32) -> u32 { - + | stack backtrace: @@ -21,8 +41,6 @@ stack backtrace: - - query stack during panic: #0 [typeck] type-checking `foo` #1 [thir_body] building THIR for `foo` From 6b8840317cd527271762dbffd45becf0e7bd098a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 11 Jan 2023 19:21:10 +0000 Subject: [PATCH 3/6] Use chrono instead of time, and permit backtrace --- Cargo.lock | 38 +++++++++++++++++++++++++++++--- compiler/rustc_driver/Cargo.toml | 2 +- compiler/rustc_driver/src/lib.rs | 19 ++++------------ src/tools/tidy/src/deps.rs | 1 + 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d1079135c0d2..6c4bf0afd0545 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -611,6 +611,16 @@ dependencies = [ "tracing-tree", ] +[[package]] +name = "chrono" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" +dependencies = [ + "num", + "time 0.1.43", +] + [[package]] name = "chrono" version = "0.4.19" @@ -2535,7 +2545,7 @@ checksum = "23f3e133c6d515528745ffd3b9f0c7d975ae039f0b6abb099f2168daa2afb4f9" dependencies = [ "ammonia", "anyhow", - "chrono", + "chrono 0.4.19", "clap 3.2.20", "clap_complete", "elasticlunr-rs", @@ -2703,6 +2713,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "num" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +dependencies = [ + "num-integer", + "num-iter", + "num-traits", +] + [[package]] name = "num-integer" version = "0.1.43" @@ -2713,6 +2734,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.12" @@ -3916,6 +3948,7 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "backtrace", + "chrono 0.2.25", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3942,7 +3975,6 @@ dependencies = [ "rustc_span", "rustc_target", "serde_json", - "time 0.3.17", "tracing", "winapi", ] @@ -5252,7 +5284,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3" dependencies = [ - "chrono", + "chrono 0.4.19", "log", "nom", "serde", diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 7bf3f8d860930..19fea87eaa6ac 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["dylib"] [dependencies] backtrace = "0.3.66" serde_json = "1.0.59" -time = { version = "0.3.17", features = ["std", "formatting"] } +chrono = "0.2" tracing = { version = "0.1.35" } rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 3a49488544796..62d9625166ba6 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1185,16 +1185,7 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { } struct IceError; -impl From for IceError { - fn from(_: time::error::InvalidFormatDescription) -> IceError { - IceError - } -} -impl From for IceError { - fn from(_: time::error::Format) -> IceError { - IceError - } -} + impl From for IceError { fn from(_: std::io::Error) -> IceError { IceError @@ -1203,11 +1194,9 @@ impl From for IceError { fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { let capture = backtrace::Backtrace::force_capture(); - let now = time::OffsetDateTime::now_utc(); - let format = time::format_description::parse("[year]-[month]-[day]_[hour]:[minute]:[second]")?; - let file_now = now.format(&format)?; - let format = time::format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]")?; - let now = now.format(&format)?; + let now = chrono::UTC::now(); + let file_now = now.format("%Y-%m-%d_%H:%M:%S"); + let now = now.format("%Y-%m-%d %H:%M:%S"); let path = format!("rustc-ice-context-{file_now}.txt"); let mut file = std::fs::File::create(&path)?; writeln!( diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 29501d2d3b6be..3cc9ad30593d0 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -96,6 +96,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "arrayvec", "atty", "autocfg", + "backtrace", "bitflags", "block-buffer", "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. From a5f518a18dc5a637d98ec0e4e9c53c121a50e962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 23:46:34 +0000 Subject: [PATCH 4/6] wip --- Cargo.lock | 7 +++++++ compiler/rustc_driver/Cargo.toml | 1 + compiler/rustc_driver/src/lib.rs | 28 +++++++++++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c4bf0afd0545..cef0721da5417 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3976,6 +3976,7 @@ dependencies = [ "rustc_target", "serde_json", "tracing", + "urlqstring", "winapi", ] @@ -6090,6 +6091,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlqstring" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ef3473a06a065718d8ec7cd7acc6a35fc20f836dee7661ad3b64ea3cc2e0cc" + [[package]] name = "utf-8" version = "0.7.5" diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 19fea87eaa6ac..fa55aefbd6e77 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["dylib"] backtrace = "0.3.66" serde_json = "1.0.59" chrono = "0.2" +urlqstring = "*" tracing = { version = "0.1.35" } rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 62d9625166ba6..39ccea4c5f482 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -9,6 +9,7 @@ #![feature(once_cell)] #![feature(decl_macro)] #![feature(panic_info_message)] +#![feature(backtrace_frames)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -1192,7 +1193,8 @@ impl From for IceError { } } -fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { +fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), IceError> { + let mut args = vec![]; let capture = backtrace::Backtrace::force_capture(); let now = chrono::UTC::now(); let file_now = now.format("%Y-%m-%d_%H:%M:%S"); @@ -1210,10 +1212,12 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { }, config::host_triple(), )?; + args.push(("version", util::version_str!().unwrap_or("unknown_version"))); + args.push(("platform", config::host_triple())); if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { writeln!(file, "compiler flags:")?; - for flag in flags { + for flag in &flags { writeln!(file, " {flag}")?; } if excluded_cargo_defaults { @@ -1221,6 +1225,8 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { } } writeln!(file, "")?; + let mut text = String::new(); + text.push_str(&format!("{:?} {:?}", info.message(), info.location())); match (info.message(), info.location()) { (Some(message), Some(location)) => { writeln!(file, "panicked at {location}:\n{message}")?; @@ -1237,7 +1243,15 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { } writeln!(file, "")?; - writeln!(file, "{}", capture)?; + let capture = capture.frames().iter().map(|frame| { + format!("{:?}", frame) + }).collect::(); + writeln!(file, "{capture}")?; + text.push_str(&format!("{capture}")); + args.push(("backtrace", &text)); + + println!("{}", text); + println!("{}", urlqstring::QueryParams::from(args).stringify()); // Be careful relying on global state here: this code is called from // a panic hook, which means that the global `Handler` may be in a weird @@ -1266,7 +1280,7 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result { writeln!(file, "end of query stack")?; Ok(()) })?; - Ok(path) + Ok((path, String::new())) } static DEFAULT_HOOK: LazyLock) + Sync + Send + 'static>> = @@ -1313,7 +1327,7 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. -pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ice: Option) { +pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ice: Option<(String, String)>) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( @@ -1341,10 +1355,10 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ic handler.emit_diagnostic(&mut d); } - let xs: Vec> = if let Some(path) = &reported_ice { + let xs: Vec> = if let Some((path, url)) = &reported_ice { vec![ format!("all necessary context about this bug was written to `{path}`").into(), - format!("we would appreciate a bug report with this context at <{bug_report_url}>") + format!("we would appreciate a bug report with this context at <{url}>") .into(), ] } else { From a9f12e2d2c0d66a326fd824a393bf584ec343c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 13 Jan 2023 18:19:29 +0000 Subject: [PATCH 5/6] wip --- Cargo.lock | 1 + compiler/rustc_codegen_llvm/src/lib.rs | 2 +- compiler/rustc_driver/Cargo.toml | 1 + compiler/rustc_driver/src/lib.rs | 46 ++++++++++++++------------ 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cef0721da5417..b10470f1001b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3952,6 +3952,7 @@ dependencies = [ "libc", "rustc_ast", "rustc_ast_pretty", + "rustc_codegen_llvm", "rustc_codegen_ssa", "rustc_data_structures", "rustc_error_codes", diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 246e82545c874..a220aa27b5be2 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -23,7 +23,7 @@ extern crate tracing; use back::write::{create_informational_target_machine, create_target_machine}; use errors::FailParsingTargetMachineConfigToTargetMachine; -pub use llvm_util::target_features; +pub use llvm_util::{get_version, target_features}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index fa55aefbd6e77..f8811feaa3a1e 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -28,6 +28,7 @@ rustc_parse = { path = "../rustc_parse" } rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_save_analysis = { path = "../rustc_save_analysis" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } +rustc_codegen_llvm = { path = "../rustc_codegen_llvm" } rustc_session = { path = "../rustc_session" } rustc_error_codes = { path = "../rustc_error_codes" } rustc_interface = { path = "../rustc_interface" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 39ccea4c5f482..757622887e828 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -76,7 +76,7 @@ pub const EXIT_SUCCESS: i32 = 0; pub const EXIT_FAILURE: i32 = 1; const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\ - ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md"; + ?labels=C-bug%2CI-ICE%2CT-compiler&template=ice.yaml"; const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"]; @@ -1199,11 +1199,12 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic let now = chrono::UTC::now(); let file_now = now.format("%Y-%m-%d_%H:%M:%S"); let now = now.format("%Y-%m-%d %H:%M:%S"); - let path = format!("rustc-ice-context-{file_now}.txt"); + let mut path = std::env::current_dir()?; + path.push(format!("rustc-ice-context-{file_now}.txt")); let mut file = std::fs::File::create(&path)?; - writeln!( - file, - "rustc {}{} running on {} at {now}", + let (llvm_major, llvm_minor, llvm_dot) = rustc_codegen_llvm::get_version(); + let version = format!( + "rustc {}{} running on {} at {now} with LLVM {llvm_major}.{llvm_minor}.{llvm_dot}", util::version_str!().unwrap_or("unknown_version"), match (option_env!("CFG_VER_HASH"), option_env!("CFG_VER_DATE")) { (Some(hash), Some(date)) => format!(" ({hash} - {date})"), @@ -1211,9 +1212,12 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic (None, None) => String::new(), }, config::host_triple(), - )?; - args.push(("version", util::version_str!().unwrap_or("unknown_version"))); - args.push(("platform", config::host_triple())); + ); + + writeln!(file, "{}", version)?; + args.push(("version", version.as_str())); + let backtrace_msg = format!("please include the contents of `{}` here", path.display()); + args.push(("backtrace", &backtrace_msg)); if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { writeln!(file, "compiler flags:")?; @@ -1243,15 +1247,7 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic } writeln!(file, "")?; - let capture = capture.frames().iter().map(|frame| { - format!("{:?}", frame) - }).collect::(); writeln!(file, "{capture}")?; - text.push_str(&format!("{capture}")); - args.push(("backtrace", &text)); - - println!("{}", text); - println!("{}", urlqstring::QueryParams::from(args).stringify()); // Be careful relying on global state here: this code is called from // a panic hook, which means that the global `Handler` may be in a weird @@ -1280,7 +1276,10 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic writeln!(file, "end of query stack")?; Ok(()) })?; - Ok((path, String::new())) + Ok(( + path.display().to_string(), + format!("{BUG_REPORT_URL}&{}", urlqstring::QueryParams::from(args).stringify()), + )) } static DEFAULT_HOOK: LazyLock) + Sync + Send + 'static>> = @@ -1327,7 +1326,11 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. -pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ice: Option<(String, String)>) { +pub fn report_ice( + info: &panic::PanicInfo<'_>, + bug_report_url: &str, + reported_ice: Option<(String, String)>, +) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( @@ -1355,11 +1358,12 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, reported_ic handler.emit_diagnostic(&mut d); } - let xs: Vec> = if let Some((path, url)) = &reported_ice { + let xs: Vec> = if let Some((path, custom_url)) = &reported_ice { + let link = format!("\x1b]8;;{custom_url}\x1b\\{bug_report_url}\x1b]8;;\x1b\\"); + let path = format!("\x1b]8;;file://{path}\x1b\\{path}\x1b]8;;\x1b\\"); vec![ format!("all necessary context about this bug was written to `{path}`").into(), - format!("we would appreciate a bug report with this context at <{url}>") - .into(), + format!("we would appreciate a bug report with this context at {link}").into(), ] } else { let mut xs = vec![ From 57161b5729d77889d1435c465fad03cd7eb69ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Jan 2023 06:08:48 +0000 Subject: [PATCH 6/6] Check CI env vars and tweak output --- Cargo.lock | 29 +++++++++++++++++++++++++++++ compiler/rustc_driver/Cargo.toml | 1 + compiler/rustc_driver/src/lib.rs | 11 ++++------- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b10470f1001b9..e1e511a51eef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -635,6 +635,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "ci_info" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62a62f39080c8c83e899dff6abd46c4fac05c1cf8dafece96ad8238e79addbf8" +dependencies = [ + "envmnt", +] + [[package]] name = "clap" version = "3.2.20" @@ -1424,6 +1433,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "envmnt" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73999a2b8871e74c8b8bc23759ee9f3d85011b24fafc91a4b3b5c8cc8185501" +dependencies = [ + "fsio", + "indexmap", +] + [[package]] name = "errno" version = "0.2.8" @@ -1629,6 +1648,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" +[[package]] +name = "fsio" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad0ce30be0cc441b325c5d705c8b613a0ca0d92b6a8953d41bd236dc09a36d0" +dependencies = [ + "dunce", +] + [[package]] name = "futf" version = "0.1.5" @@ -3949,6 +3977,7 @@ version = "0.0.0" dependencies = [ "backtrace", "chrono 0.2.25", + "ci_info", "libc", "rustc_ast", "rustc_ast_pretty", diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index f8811feaa3a1e..a2d6b5f07e2fb 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["dylib"] backtrace = "0.3.66" serde_json = "1.0.59" chrono = "0.2" +ci_info = "0.14.9" urlqstring = "*" tracing = { version = "0.1.35" } rustc_log = { path = "../rustc_log" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 757622887e828..7e7997a84f840 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1216,8 +1216,6 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic writeln!(file, "{}", version)?; args.push(("version", version.as_str())); - let backtrace_msg = format!("please include the contents of `{}` here", path.display()); - args.push(("backtrace", &backtrace_msg)); if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { writeln!(file, "compiler flags:")?; @@ -1229,8 +1227,6 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic } } writeln!(file, "")?; - let mut text = String::new(); - text.push_str(&format!("{:?} {:?}", info.message(), info.location())); match (info.message(), info.location()) { (Some(message), Some(location)) => { writeln!(file, "panicked at {location}:\n{message}")?; @@ -1247,6 +1243,7 @@ fn write_ice_to_disk(info: &panic::PanicInfo<'_>) -> Result<(String, String), Ic } writeln!(file, "")?; + let capture = format!("{capture}"); writeln!(file, "{capture}")?; // Be careful relying on global state here: this code is called from @@ -1304,7 +1301,8 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + && std::env::var("RUSTC_BACKTRACE_FORCE").as_deref() != Ok("0") }, ); - let written_ice = if !is_dev { write_ice_to_disk(info) } else { Err(IceError) }; + let written_ice = + if !is_dev && !ci_info::is_ci() { write_ice_to_disk(info) } else { Err(IceError) }; // Invoke the default handler, which prints the actual panic message and optionally a backtrace // Don't do this for delayed bugs, which already emit their own more useful backtrace. if !info.payload().is::() && written_ice.is_err() { @@ -1359,8 +1357,7 @@ pub fn report_ice( } let xs: Vec> = if let Some((path, custom_url)) = &reported_ice { - let link = format!("\x1b]8;;{custom_url}\x1b\\{bug_report_url}\x1b]8;;\x1b\\"); - let path = format!("\x1b]8;;file://{path}\x1b\\{path}\x1b]8;;\x1b\\"); + let link = format!("\x1b]8;;{custom_url}\x07{bug_report_url}\x1b]8;;\x07"); vec![ format!("all necessary context about this bug was written to `{path}`").into(), format!("we would appreciate a bug report with this context at {link}").into(),