mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
On nightly, dump ICE backtraces to disk
Implement rust-lang/compiler-team#578. When an ICE is encountered on nightly releases, the new rustc panic handler will also write the contents of the backtrace to disk. If any `delay_span_bug`s are encountered, their backtrace is also added to the file. The platform and rustc version will also be collected.
This commit is contained in:
parent
77e24f90f5
commit
8eb5843a59
28
Cargo.lock
28
Cargo.lock
@ -3488,6 +3488,7 @@ dependencies = [
|
|||||||
"rustc_trait_selection",
|
"rustc_trait_selection",
|
||||||
"rustc_ty_utils",
|
"rustc_ty_utils",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
@ -5142,6 +5143,33 @@ dependencies = [
|
|||||||
name = "tier-check"
|
name = "tier-check"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
|
||||||
|
dependencies = [
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -362,7 +362,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
|||||||
|
|
||||||
impl<B: WriteBackendMethods> CodegenContext<B> {
|
impl<B: WriteBackendMethods> CodegenContext<B> {
|
||||||
pub fn create_diag_handler(&self) -> Handler {
|
pub fn create_diag_handler(&self) -> Handler {
|
||||||
Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()))
|
Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
|
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
|
||||||
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
time = { version = "0.3", default-features = false, features = ["formatting", ] }
|
||||||
tracing = { version = "0.1.35" }
|
tracing = { version = "0.1.35" }
|
||||||
serde_json = "1.0.59"
|
serde_json = "1.0.59"
|
||||||
rustc_log = { path = "../rustc_log" }
|
rustc_log = { path = "../rustc_log" }
|
||||||
|
@ -3,7 +3,11 @@ driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
|||||||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||||
|
|
||||||
driver_impl_ice_flags = compiler flags: {$flags}
|
driver_impl_ice_flags = compiler flags: {$flags}
|
||||||
|
driver_impl_ice_path = please attach the file at `{$path}` to your bug report
|
||||||
|
driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error}
|
||||||
|
driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}`
|
||||||
driver_impl_ice_version = rustc {$version} running on {$triple}
|
driver_impl_ice_version = rustc {$version} running on {$triple}
|
||||||
|
|
||||||
driver_impl_rlink_empty_version_number = The input does not contain version number
|
driver_impl_rlink_empty_version_number = The input does not contain version number
|
||||||
|
|
||||||
driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
|
driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(lazy_cell)]
|
#![feature(lazy_cell)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
|
#![feature(ice_to_disk)]
|
||||||
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
@ -57,8 +59,11 @@ use std::panic::{self, catch_unwind};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{self, Command, Stdio};
|
use std::process::{self, Command, Stdio};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::time::Instant;
|
use std::time::{Instant, SystemTime};
|
||||||
|
use time::format_description::well_known::Rfc3339;
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro do_not_use_print($($t:tt)*) {
|
macro do_not_use_print($($t:tt)*) {
|
||||||
@ -294,6 +299,7 @@ fn run_compiler(
|
|||||||
input: Input::File(PathBuf::new()),
|
input: Input::File(PathBuf::new()),
|
||||||
output_file: ofile,
|
output_file: ofile,
|
||||||
output_dir: odir,
|
output_dir: odir,
|
||||||
|
ice_file: ice_path().clone(),
|
||||||
file_loader,
|
file_loader,
|
||||||
locale_resources: DEFAULT_LOCALE_RESOURCES,
|
locale_resources: DEFAULT_LOCALE_RESOURCES,
|
||||||
lint_caps: Default::default(),
|
lint_caps: Default::default(),
|
||||||
@ -1292,9 +1298,29 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores the default panic hook, from before [`install_ice_hook`] was called.
|
pub static ICE_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
|
||||||
static DEFAULT_HOOK: OnceLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
|
|
||||||
OnceLock::new();
|
pub fn ice_path() -> &'static Option<PathBuf> {
|
||||||
|
ICE_PATH.get_or_init(|| {
|
||||||
|
if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if let Ok("0") = std::env::var("RUST_BACKTRACE").as_deref() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut path = match std::env::var("RUSTC_ICE").as_deref() {
|
||||||
|
// Explicitly opting out of writing ICEs to disk.
|
||||||
|
Ok("0") => return None,
|
||||||
|
Ok(s) => PathBuf::from(s),
|
||||||
|
Err(_) => std::env::current_dir().unwrap_or_default(),
|
||||||
|
};
|
||||||
|
let now: OffsetDateTime = SystemTime::now().into();
|
||||||
|
let file_now = now.format(&Rfc3339).unwrap_or(String::new());
|
||||||
|
let pid = std::process::id();
|
||||||
|
path.push(format!("rustc-ice-{file_now}-{pid}.txt"));
|
||||||
|
Some(path)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Installs a panic hook that will print the ICE message on unexpected panics.
|
/// Installs a panic hook that will print the ICE message on unexpected panics.
|
||||||
///
|
///
|
||||||
@ -1318,8 +1344,6 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
|
|||||||
std::env::set_var("RUST_BACKTRACE", "full");
|
std::env::set_var("RUST_BACKTRACE", "full");
|
||||||
}
|
}
|
||||||
|
|
||||||
let default_hook = DEFAULT_HOOK.get_or_init(panic::take_hook);
|
|
||||||
|
|
||||||
panic::set_hook(Box::new(move |info| {
|
panic::set_hook(Box::new(move |info| {
|
||||||
// If the error was caused by a broken pipe then this is not a bug.
|
// If the error was caused by a broken pipe then this is not a bug.
|
||||||
// Write the error and return immediately. See #98700.
|
// Write the error and return immediately. See #98700.
|
||||||
@ -1336,7 +1360,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
|
|||||||
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
|
// 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.
|
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
|
||||||
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
|
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
|
||||||
(*default_hook)(info);
|
std::panic_hook_with_disk_dump(info, ice_path().as_deref());
|
||||||
|
|
||||||
// Separate the output with an empty line
|
// Separate the output with an empty line
|
||||||
eprintln!();
|
eprintln!();
|
||||||
@ -1368,7 +1392,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||||||
false,
|
false,
|
||||||
TerminalUrl::No,
|
TerminalUrl::No,
|
||||||
));
|
));
|
||||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
let handler = rustc_errors::Handler::with_emitter(true, None, emitter, None);
|
||||||
|
|
||||||
// a .span_bug or .bug call has already printed what
|
// a .span_bug or .bug call has already printed what
|
||||||
// it wants to print.
|
// it wants to print.
|
||||||
@ -1379,10 +1403,40 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||||
handler.emit_note(session_diagnostics::IceVersion {
|
|
||||||
version: util::version_str!().unwrap_or("unknown_version"),
|
let version = util::version_str!().unwrap_or("unknown_version");
|
||||||
triple: config::host_triple(),
|
let triple = config::host_triple();
|
||||||
});
|
|
||||||
|
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||||
|
|
||||||
|
let file = if let Some(path) = ice_path().as_ref() {
|
||||||
|
// Create the ICE dump target file.
|
||||||
|
match crate::fs::File::options().create(true).append(true).open(&path) {
|
||||||
|
Ok(mut file) => {
|
||||||
|
handler
|
||||||
|
.emit_note(session_diagnostics::IcePath { path: path.display().to_string() });
|
||||||
|
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||||
|
let _ = write!(file, "\n\nrustc version: {version}\nplatform: {triple}");
|
||||||
|
}
|
||||||
|
Some(file)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
// The path ICE couldn't be written to disk, provide feedback to the user as to why.
|
||||||
|
handler.emit_warning(session_diagnostics::IcePathError {
|
||||||
|
path: path.display().to_string(),
|
||||||
|
error: err.to_string(),
|
||||||
|
env_var: std::env::var("RUSTC_ICE")
|
||||||
|
.ok()
|
||||||
|
.map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }),
|
||||||
|
});
|
||||||
|
handler.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handler.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
||||||
handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
|
handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
|
||||||
@ -1396,7 +1450,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||||||
|
|
||||||
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, file);
|
||||||
|
|
||||||
// We don't trust this callback not to panic itself, so run it at the end after we're sure we've
|
// We don't trust this callback not to panic itself, so run it at the end after we're sure we've
|
||||||
// printed all the relevant info.
|
// printed all the relevant info.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(driver_impl_rlink_unable_to_read)]
|
#[diag(driver_impl_rlink_unable_to_read)]
|
||||||
@ -56,6 +56,27 @@ pub(crate) struct IceVersion<'a> {
|
|||||||
pub triple: &'a str,
|
pub triple: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(driver_impl_ice_path)]
|
||||||
|
pub(crate) struct IcePath {
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(driver_impl_ice_path_error)]
|
||||||
|
pub(crate) struct IcePathError {
|
||||||
|
pub path: String,
|
||||||
|
pub error: String,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub env_var: Option<IcePathErrorEnv>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(driver_impl_ice_path_error_env)]
|
||||||
|
pub(crate) struct IcePathErrorEnv {
|
||||||
|
pub env_var: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(driver_impl_ice_flags)]
|
#[diag(driver_impl_ice_flags)]
|
||||||
pub(crate) struct IceFlags {
|
pub(crate) struct IceFlags {
|
||||||
|
@ -354,6 +354,13 @@ impl DiagnosticMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
|
||||||
|
DiagnosticMessage::FluentIdentifier(_, _) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for DiagnosticMessage {
|
impl From<String> for DiagnosticMessage {
|
||||||
|
@ -64,7 +64,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
||||||
let handler = Handler::with_emitter(true, None, Box::new(je));
|
let handler = Handler::with_emitter(true, None, Box::new(je), None);
|
||||||
handler.span_err(span, "foo");
|
handler.span_err(span, "foo");
|
||||||
|
|
||||||
let bytes = output.lock().unwrap();
|
let bytes = output.lock().unwrap();
|
||||||
|
@ -47,9 +47,10 @@ use std::borrow::Cow;
|
|||||||
use std::error::Report;
|
use std::error::Report;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::io::Write;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::panic;
|
use std::panic;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use termcolor::{Color, ColorSpec};
|
use termcolor::{Color, ColorSpec};
|
||||||
|
|
||||||
@ -461,6 +462,10 @@ struct HandlerInner {
|
|||||||
///
|
///
|
||||||
/// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
|
/// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
|
||||||
fulfilled_expectations: FxHashSet<LintExpectationId>,
|
fulfilled_expectations: FxHashSet<LintExpectationId>,
|
||||||
|
|
||||||
|
/// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be
|
||||||
|
/// stored along side the main panic backtrace.
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A key denoting where from a diagnostic was stashed.
|
/// A key denoting where from a diagnostic was stashed.
|
||||||
@ -550,6 +555,7 @@ impl Handler {
|
|||||||
sm: Option<Lrc<SourceMap>>,
|
sm: Option<Lrc<SourceMap>>,
|
||||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: LazyFallbackBundle,
|
fallback_bundle: LazyFallbackBundle,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::with_tty_emitter_and_flags(
|
Self::with_tty_emitter_and_flags(
|
||||||
color_config,
|
color_config,
|
||||||
@ -557,6 +563,7 @@ impl Handler {
|
|||||||
fluent_bundle,
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
||||||
|
ice_file,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,6 +573,7 @@ impl Handler {
|
|||||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: LazyFallbackBundle,
|
fallback_bundle: LazyFallbackBundle,
|
||||||
flags: HandlerFlags,
|
flags: HandlerFlags,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let emitter = Box::new(EmitterWriter::stderr(
|
let emitter = Box::new(EmitterWriter::stderr(
|
||||||
color_config,
|
color_config,
|
||||||
@ -579,23 +587,26 @@ impl Handler {
|
|||||||
flags.track_diagnostics,
|
flags.track_diagnostics,
|
||||||
TerminalUrl::No,
|
TerminalUrl::No,
|
||||||
));
|
));
|
||||||
Self::with_emitter_and_flags(emitter, flags)
|
Self::with_emitter_and_flags(emitter, flags, ice_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_emitter(
|
pub fn with_emitter(
|
||||||
can_emit_warnings: bool,
|
can_emit_warnings: bool,
|
||||||
treat_err_as_bug: Option<NonZeroUsize>,
|
treat_err_as_bug: Option<NonZeroUsize>,
|
||||||
emitter: Box<dyn Emitter + sync::Send>,
|
emitter: Box<dyn Emitter + sync::Send>,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Handler::with_emitter_and_flags(
|
Handler::with_emitter_and_flags(
|
||||||
emitter,
|
emitter,
|
||||||
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
||||||
|
ice_file,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_emitter_and_flags(
|
pub fn with_emitter_and_flags(
|
||||||
emitter: Box<dyn Emitter + sync::Send>,
|
emitter: Box<dyn Emitter + sync::Send>,
|
||||||
flags: HandlerFlags,
|
flags: HandlerFlags,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
flags,
|
flags,
|
||||||
@ -618,6 +629,7 @@ impl Handler {
|
|||||||
check_unstable_expect_diagnostics: false,
|
check_unstable_expect_diagnostics: false,
|
||||||
unstable_expect_diagnostics: Vec::new(),
|
unstable_expect_diagnostics: Vec::new(),
|
||||||
fulfilled_expectations: Default::default(),
|
fulfilled_expectations: Default::default(),
|
||||||
|
ice_file,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1657,8 +1669,21 @@ impl HandlerInner {
|
|||||||
explanation: impl Into<DiagnosticMessage> + Copy,
|
explanation: impl Into<DiagnosticMessage> + Copy,
|
||||||
) {
|
) {
|
||||||
let mut no_bugs = true;
|
let mut no_bugs = true;
|
||||||
|
// If backtraces are enabled, also print the query stack
|
||||||
|
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
|
||||||
for bug in bugs {
|
for bug in bugs {
|
||||||
let mut bug = bug.decorate();
|
if let Some(file) = self.ice_file.as_ref()
|
||||||
|
&& let Ok(mut out) = std::fs::File::options().append(true).open(file)
|
||||||
|
{
|
||||||
|
let _ = write!(
|
||||||
|
&mut out,
|
||||||
|
"\n\ndelayed span bug: {}\n{}",
|
||||||
|
bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
|
||||||
|
&bug.note
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let mut bug =
|
||||||
|
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||||
|
|
||||||
if no_bugs {
|
if no_bugs {
|
||||||
// Put the overall explanation before the `DelayedBug`s, to
|
// Put the overall explanation before the `DelayedBug`s, to
|
||||||
|
@ -161,7 +161,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
|||||||
false,
|
false,
|
||||||
TerminalUrl::No,
|
TerminalUrl::No,
|
||||||
);
|
);
|
||||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
let handler = Handler::with_emitter(true, None, Box::new(emitter), None);
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
handler.span_err(msp, "foo");
|
handler.span_err(msp, "foo");
|
||||||
|
|
||||||
|
@ -251,6 +251,7 @@ pub struct Config {
|
|||||||
pub input: Input,
|
pub input: Input,
|
||||||
pub output_dir: Option<PathBuf>,
|
pub output_dir: Option<PathBuf>,
|
||||||
pub output_file: Option<OutFileName>,
|
pub output_file: Option<OutFileName>,
|
||||||
|
pub ice_file: Option<PathBuf>,
|
||||||
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
|
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
|
||||||
pub locale_resources: &'static [&'static str],
|
pub locale_resources: &'static [&'static str],
|
||||||
|
|
||||||
@ -315,6 +316,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||||||
config.lint_caps,
|
config.lint_caps,
|
||||||
config.make_codegen_backend,
|
config.make_codegen_backend,
|
||||||
registry.clone(),
|
registry.clone(),
|
||||||
|
config.ice_file,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(parse_sess_created) = config.parse_sess_created {
|
if let Some(parse_sess_created) = config.parse_sess_created {
|
||||||
@ -346,7 +348,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
pub fn try_print_query_stack(
|
||||||
|
handler: &Handler,
|
||||||
|
num_frames: Option<usize>,
|
||||||
|
file: Option<std::fs::File>,
|
||||||
|
) {
|
||||||
eprintln!("query stack during panic:");
|
eprintln!("query stack during panic:");
|
||||||
|
|
||||||
// Be careful relying on global state here: this code is called from
|
// Be careful relying on global state here: this code is called from
|
||||||
@ -358,7 +364,8 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
|||||||
QueryCtxt::new(icx.tcx),
|
QueryCtxt::new(icx.tcx),
|
||||||
icx.query,
|
icx.query,
|
||||||
handler,
|
handler,
|
||||||
num_frames
|
num_frames,
|
||||||
|
file,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -67,6 +67,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
|
|||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
"",
|
"",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
(sess, cfg)
|
(sess, cfg)
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ pub fn create_session(
|
|||||||
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
|
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
|
||||||
>,
|
>,
|
||||||
descriptions: Registry,
|
descriptions: Registry,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> (Session, Box<dyn CodegenBackend>) {
|
) -> (Session, Box<dyn CodegenBackend>) {
|
||||||
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
|
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
|
||||||
make_codegen_backend(&sopts)
|
make_codegen_backend(&sopts)
|
||||||
@ -111,6 +112,7 @@ pub fn create_session(
|
|||||||
file_loader,
|
file_loader,
|
||||||
target_override,
|
target_override,
|
||||||
rustc_version_str().unwrap_or("unknown"),
|
rustc_version_str().unwrap_or("unknown"),
|
||||||
|
ice_file,
|
||||||
);
|
);
|
||||||
|
|
||||||
codegen_backend.init(&sess);
|
codegen_backend.init(&sess);
|
||||||
|
@ -13,6 +13,7 @@ use rustc_session::Session;
|
|||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::io::Write;
|
||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
@ -617,30 +618,50 @@ pub fn print_query_stack<Qcx: QueryContext>(
|
|||||||
mut current_query: Option<QueryJobId>,
|
mut current_query: Option<QueryJobId>,
|
||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
num_frames: Option<usize>,
|
num_frames: Option<usize>,
|
||||||
|
mut file: Option<std::fs::File>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
// Be careful relying on global state here: this code is called from
|
// 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
|
// a panic hook, which means that the global `Handler` may be in a weird
|
||||||
// state if it was responsible for triggering the panic.
|
// state if it was responsible for triggering the panic.
|
||||||
let mut i = 0;
|
let mut count_printed = 0;
|
||||||
|
let mut count_total = 0;
|
||||||
let query_map = qcx.try_collect_active_jobs();
|
let query_map = qcx.try_collect_active_jobs();
|
||||||
|
|
||||||
|
if let Some(ref mut file) = file {
|
||||||
|
let _ = writeln!(file, "\n\nquery stack during panic:");
|
||||||
|
}
|
||||||
while let Some(query) = current_query {
|
while let Some(query) = current_query {
|
||||||
if Some(i) == num_frames {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
|
let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
let mut diag = Diagnostic::new(
|
if Some(count_printed) < num_frames || num_frames.is_none() {
|
||||||
Level::FailureNote,
|
// Only print to stderr as many stack frames as `num_frames` when present.
|
||||||
format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description),
|
let mut diag = Diagnostic::new(
|
||||||
);
|
Level::FailureNote,
|
||||||
diag.span = query_info.job.span.into();
|
format!(
|
||||||
handler.force_print_diagnostic(diag);
|
"#{} [{:?}] {}",
|
||||||
|
count_printed, query_info.query.dep_kind, query_info.query.description
|
||||||
|
),
|
||||||
|
);
|
||||||
|
diag.span = query_info.job.span.into();
|
||||||
|
handler.force_print_diagnostic(diag);
|
||||||
|
count_printed += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut file) = file {
|
||||||
|
let _ = writeln!(
|
||||||
|
file,
|
||||||
|
"#{} [{:?}] {}",
|
||||||
|
count_total, query_info.query.dep_kind, query_info.query.description
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
current_query = query_info.job.parent;
|
current_query = query_info.job.parent;
|
||||||
i += 1;
|
count_total += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i
|
if let Some(ref mut file) = file {
|
||||||
|
let _ = writeln!(file, "end of query stack");
|
||||||
|
}
|
||||||
|
count_printed
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,7 @@ impl ParseSess {
|
|||||||
Some(sm.clone()),
|
Some(sm.clone()),
|
||||||
None,
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
ParseSess::with_span_handler(handler, sm)
|
ParseSess::with_span_handler(handler, sm)
|
||||||
}
|
}
|
||||||
@ -261,12 +262,20 @@ impl ParseSess {
|
|||||||
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
|
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
|
||||||
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
|
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let fatal_handler =
|
let fatal_handler = Handler::with_tty_emitter(
|
||||||
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
|
ColorConfig::Auto,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
fallback_bundle,
|
||||||
|
None,
|
||||||
|
);
|
||||||
let handler = Handler::with_emitter(
|
let handler = Handler::with_emitter(
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
Box::new(SilentEmitter { fatal_handler, fatal_note }),
|
Box::new(SilentEmitter { fatal_handler, fatal_note }),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
ParseSess::with_span_handler(handler, sm)
|
ParseSess::with_span_handler(handler, sm)
|
||||||
}
|
}
|
||||||
|
@ -1392,6 +1392,7 @@ pub fn build_session(
|
|||||||
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
|
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
|
||||||
target_override: Option<Target>,
|
target_override: Option<Target>,
|
||||||
cfg_version: &'static str,
|
cfg_version: &'static str,
|
||||||
|
ice_file: Option<PathBuf>,
|
||||||
) -> Session {
|
) -> Session {
|
||||||
// FIXME: This is not general enough to make the warning lint completely override
|
// FIXME: This is not general enough to make the warning lint completely override
|
||||||
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
||||||
@ -1440,6 +1441,7 @@ pub fn build_session(
|
|||||||
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
|
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
|
||||||
emitter,
|
emitter,
|
||||||
sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings),
|
sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings),
|
||||||
|
ice_file,
|
||||||
);
|
);
|
||||||
|
|
||||||
let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
|
let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
|
||||||
@ -1731,7 +1733,7 @@ pub struct EarlyErrorHandler {
|
|||||||
impl EarlyErrorHandler {
|
impl EarlyErrorHandler {
|
||||||
pub fn new(output: ErrorOutputType) -> Self {
|
pub fn new(output: ErrorOutputType) -> Self {
|
||||||
let emitter = mk_emitter(output);
|
let emitter = mk_emitter(output);
|
||||||
Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter) }
|
Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter, None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn abort_if_errors(&self) {
|
pub fn abort_if_errors(&self) {
|
||||||
@ -1745,7 +1747,7 @@ impl EarlyErrorHandler {
|
|||||||
self.handler.abort_if_errors();
|
self.handler.abort_if_errors();
|
||||||
|
|
||||||
let emitter = mk_emitter(output);
|
let emitter = mk_emitter(output);
|
||||||
self.handler = Handler::with_emitter(true, None, emitter);
|
self.handler = Handler::with_emitter(true, None, emitter, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
|
@ -604,6 +604,9 @@ pub mod alloc;
|
|||||||
// Private support modules
|
// Private support modules
|
||||||
mod panicking;
|
mod panicking;
|
||||||
|
|
||||||
|
#[unstable(feature = "ice_to_disk", issue = "none")]
|
||||||
|
pub use panicking::panic_hook_with_disk_dump;
|
||||||
|
|
||||||
#[path = "../../backtrace/src/lib.rs"]
|
#[path = "../../backtrace/src/lib.rs"]
|
||||||
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
|
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
|
||||||
mod backtrace_rs;
|
mod backtrace_rs;
|
||||||
|
@ -234,7 +234,16 @@ where
|
|||||||
*hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
|
*hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The default panic handler.
|
||||||
fn default_hook(info: &PanicInfo<'_>) {
|
fn default_hook(info: &PanicInfo<'_>) {
|
||||||
|
panic_hook_with_disk_dump(info, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ice_to_disk", issue = "none")]
|
||||||
|
/// The implementation of the default panic handler.
|
||||||
|
///
|
||||||
|
/// It can also write the backtrace to a given `path`. This functionality is used only by `rustc`.
|
||||||
|
pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path::Path>) {
|
||||||
// If this is a double panic, make sure that we print a backtrace
|
// If this is a double panic, make sure that we print a backtrace
|
||||||
// for this panic. Otherwise only print it if logging is enabled.
|
// for this panic. Otherwise only print it if logging is enabled.
|
||||||
let backtrace = if panic_count::get_count() >= 2 {
|
let backtrace = if panic_count::get_count() >= 2 {
|
||||||
@ -256,7 +265,7 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||||||
let thread = thread_info::current_thread();
|
let thread = thread_info::current_thread();
|
||||||
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
||||||
|
|
||||||
let write = |err: &mut dyn crate::io::Write| {
|
let write = |err: &mut dyn crate::io::Write, backtrace: Option<BacktraceStyle>| {
|
||||||
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
|
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
|
||||||
|
|
||||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||||
@ -270,10 +279,19 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||||||
}
|
}
|
||||||
Some(BacktraceStyle::Off) => {
|
Some(BacktraceStyle::Off) => {
|
||||||
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||||
let _ = writeln!(
|
if let Some(path) = path {
|
||||||
err,
|
let _ = writeln!(
|
||||||
"note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace"
|
err,
|
||||||
);
|
"note: a backtrace for this error was stored at `{}`",
|
||||||
|
path.display(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let _ = writeln!(
|
||||||
|
err,
|
||||||
|
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
|
||||||
|
backtrace"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If backtraces aren't supported, do nothing.
|
// If backtraces aren't supported, do nothing.
|
||||||
@ -281,11 +299,17 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(path) = path
|
||||||
|
&& let Ok(mut out) = crate::fs::File::options().create(true).write(true).open(&path)
|
||||||
|
{
|
||||||
|
write(&mut out, BacktraceStyle::full());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(local) = set_output_capture(None) {
|
if let Some(local) = set_output_capture(None) {
|
||||||
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
|
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()), backtrace);
|
||||||
set_output_capture(Some(local));
|
set_output_capture(Some(local));
|
||||||
} else if let Some(mut out) = panic_output() {
|
} else if let Some(mut out) = panic_output() {
|
||||||
write(&mut out);
|
write(&mut out, backtrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +176,7 @@ pub(crate) fn new_handler(
|
|||||||
rustc_errors::Handler::with_emitter_and_flags(
|
rustc_errors::Handler::with_emitter_and_flags(
|
||||||
emitter,
|
emitter,
|
||||||
unstable_opts.diagnostic_handler_flags(true),
|
unstable_opts.diagnostic_handler_flags(true),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,6 +297,7 @@ pub(crate) fn create_config(
|
|||||||
}),
|
}),
|
||||||
make_codegen_backend: None,
|
make_codegen_backend: None,
|
||||||
registry: rustc_driver::diagnostics_registry(),
|
registry: rustc_driver::diagnostics_registry(),
|
||||||
|
ice_file: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
|
|||||||
override_queries: None,
|
override_queries: None,
|
||||||
make_codegen_backend: None,
|
make_codegen_backend: None,
|
||||||
registry: rustc_driver::diagnostics_registry(),
|
registry: rustc_driver::diagnostics_registry(),
|
||||||
|
ice_file: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let test_args = options.test_args.clone();
|
let test_args = options.test_args.clone();
|
||||||
@ -586,7 +587,7 @@ pub(crate) fn make_test(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
let handler = Handler::with_emitter(false, None, Box::new(emitter), None);
|
||||||
let sess = ParseSess::with_span_handler(handler, sm);
|
let sess = ParseSess::with_span_handler(handler, sm);
|
||||||
|
|
||||||
let mut found_main = false;
|
let mut found_main = false;
|
||||||
@ -773,7 +774,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
|
|||||||
TerminalUrl::No,
|
TerminalUrl::No,
|
||||||
);
|
);
|
||||||
|
|
||||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
let handler = Handler::with_emitter(false, None, Box::new(emitter), None);
|
||||||
let sess = ParseSess::with_span_handler(handler, sm);
|
let sess = ParseSess::with_span_handler(handler, sm);
|
||||||
let mut parser =
|
let mut parser =
|
||||||
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
|
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
|
||||||
|
@ -40,7 +40,7 @@ fn check_rust_syntax(
|
|||||||
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
|
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
|
||||||
|
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
let handler = Handler::with_emitter(false, None, Box::new(emitter), None);
|
||||||
let source = dox[code_block.code].to_owned();
|
let source = dox[code_block.code].to_owned();
|
||||||
let sess = ParseSess::with_span_handler(handler, sm);
|
let sess = ParseSess::with_span_handler(handler, sm);
|
||||||
|
|
||||||
|
@ -729,7 +729,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
|||||||
false,
|
false,
|
||||||
TerminalUrl::No,
|
TerminalUrl::No,
|
||||||
);
|
);
|
||||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
let handler = Handler::with_emitter(false, None, Box::new(emitter), None);
|
||||||
let sess = ParseSess::with_span_handler(handler, sm);
|
let sess = ParseSess::with_span_handler(handler, sm);
|
||||||
|
|
||||||
let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
|
let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
|
||||||
|
@ -232,7 +232,7 @@ impl TestProps {
|
|||||||
aux_builds: vec![],
|
aux_builds: vec![],
|
||||||
aux_crates: vec![],
|
aux_crates: vec![],
|
||||||
revisions: vec![],
|
revisions: vec![],
|
||||||
rustc_env: vec![],
|
rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
|
||||||
unset_rustc_env: vec![],
|
unset_rustc_env: vec![],
|
||||||
exec_env: vec![],
|
exec_env: vec![],
|
||||||
unset_exec_env: vec![],
|
unset_exec_env: vec![],
|
||||||
|
@ -162,6 +162,7 @@ fn default_handler(
|
|||||||
ignore_path_set,
|
ignore_path_set,
|
||||||
can_reset,
|
can_reset,
|
||||||
}),
|
}),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +234,7 @@ impl ParseSess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_silent_emitter(&mut self) {
|
pub(crate) fn set_silent_emitter(&mut self) {
|
||||||
self.parse_sess.span_diagnostic = Handler::with_emitter(true, None, silent_emitter());
|
self.parse_sess.span_diagnostic = Handler::with_emitter(true, None, silent_emitter(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn span_to_filename(&self, span: Span) -> FileName {
|
pub(crate) fn span_to_filename(&self, span: Span) -> FileName {
|
||||||
|
@ -253,6 +253,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
|||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
"thorin-dwp",
|
"thorin-dwp",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"time",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
"tinystr",
|
"tinystr",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
"tinyvec_macros",
|
"tinyvec_macros",
|
||||||
|
@ -52,6 +52,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
|||||||
input,
|
input,
|
||||||
output_file: Some(OutFileName::Real(output)),
|
output_file: Some(OutFileName::Real(output)),
|
||||||
output_dir: None,
|
output_dir: None,
|
||||||
|
ice_file: None,
|
||||||
file_loader: None,
|
file_loader: None,
|
||||||
locale_resources: &[],
|
locale_resources: &[],
|
||||||
lint_caps: Default::default(),
|
lint_caps: Default::default(),
|
||||||
|
@ -5,7 +5,7 @@ all:
|
|||||||
$(RUSTC) success.rs; [ $$? -eq 0 ]
|
$(RUSTC) success.rs; [ $$? -eq 0 ]
|
||||||
$(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ]
|
$(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||||
$(RUSTC) compile-error.rs; [ $$? -eq 1 ]
|
$(RUSTC) compile-error.rs; [ $$? -eq 1 ]
|
||||||
$(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ]
|
RUSTC_ICE=0 $(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ]
|
||||||
$(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ]
|
$(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ]
|
||||||
$(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ]
|
$(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||||
$(RUSTDOC) compile-error.rs; [ $$? -eq 1 ]
|
$(RUSTDOC) compile-error.rs; [ $$? -eq 1 ]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
export RUSTC_ICE=0
|
||||||
RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
|
RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
|
||||||
RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
|
RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// compile-flags: -Ztreat-err-as-bug
|
// compile-flags: -Ztreat-err-as-bug
|
||||||
|
// rustc-env:RUSTC_ICE=0
|
||||||
// failure-status: 101
|
// failure-status: 101
|
||||||
// error-pattern: aborting due to
|
// error-pattern: aborting due to
|
||||||
// error-pattern: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md
|
// error-pattern: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
||||||
--> $DIR/ice-bug-report-url.rs:13:10
|
--> $DIR/ice-bug-report-url.rs:14:10
|
||||||
|
|
|
|
||||||
LL | fn wrong()
|
LL | fn wrong()
|
||||||
| ^ expected one of `->`, `where`, or `{`
|
| ^ expected one of `->`, `where`, or `{`
|
||||||
|
Loading…
Reference in New Issue
Block a user