diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ace4dff46aa0a..79c3aab314b94 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1325,6 +1325,7 @@ symbols! { panic_abort, panic_bounds_check, panic_cannot_unwind, + panic_color_errors, panic_const_add_overflow, panic_const_async_fn_resumed, panic_const_async_fn_resumed_panic, diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index e63b46ab70548..5431c53d6dbd5 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -42,6 +42,9 @@ pub use crate::panicking::{set_hook, take_hook}; #[unstable(feature = "panic_update_hook", issue = "92649")] pub use crate::panicking::update_hook; +#[unstable(feature = "panic_color_errors", issue = "none")] +pub use crate::panicking::highlight_errors; + #[stable(feature = "panic_hooks", since = "1.10.0")] pub use core::panic::{Location, PanicInfo}; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 5699937cdb49b..2a9142a7dbeaf 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -23,6 +23,8 @@ use crate::sys::stdio::panic_output; use crate::sys_common::backtrace; use crate::thread; +use crate::io::{self, IsTerminal}; + #[cfg(not(test))] use crate::io::try_set_output_capture; // make sure to use the stderr output configured @@ -233,6 +235,42 @@ where *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info))); } +/// Adjusts the visual representation of panic messages by enabling or +/// disabling color highlighting, or leaving it with a default behaviour. This +/// function sets, unsets or removes an environment variable (RUST_COLOR_ERRORS) +/// accordingly, influencing downstream formatting functions to produce colorful +/// error messages. +#[unstable(feature = "panic_color_errors", issue = "none")] +pub fn highlight_errors(set_color: Option){ + match set_color { + Some(true) => {crate::env::set_var("RUST_COLOR_ERRORS", "1")} + Some(false) => {crate::env::set_var("RUST_COLOR_ERRORS", "0")} + _ => {crate::env::remove_var("RUST_COLOR_ERRORS")} + } +} + +/// Alters the format of error messages by adding color codes to them. +/// It reads the RUST_COLOR_ERRORS environment variable to determine whether to +/// apply color formatting. If enabled, it formats the error message with ANSI +/// escape codes to display it in red, indicating an error state. The default +/// behavior is to apply highlighting when printing to a terminal, and no +/// highlighting otherwise. +#[unstable(feature = "panic_color_errors", issue = "none")] +fn format_error_message (msg: &str) -> String { + match crate::env::var_os("RUST_COLOR_ERRORS") { + Some(x) if x == "1" => format!("\x1b[31m{msg}\x1b[0m"), + None => { + if io::stderr().is_terminal() { + format!("\x1b[31m{msg}\x1b[0m") + } + else { + msg.to_string() + } + }, + _ => msg.to_string() + } +} + /// The default panic handler. fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace @@ -259,7 +297,10 @@ fn default_hook(info: &PanicInfo<'_>) { let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut dyn crate::io::Write| { - let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + // We should check if the feature is active and only then procede to format the message, but we dont know how to do it for now. + let msg_fmt = format_error_message(msg); + + let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg_fmt}"); static FIRST_PANIC: AtomicBool = AtomicBool::new(true); diff --git a/src/doc/unstable-book/src/library-features/panic-color-errors.md b/src/doc/unstable-book/src/library-features/panic-color-errors.md new file mode 100644 index 0000000000000..97acc2bd2951b --- /dev/null +++ b/src/doc/unstable-book/src/library-features/panic-color-errors.md @@ -0,0 +1,7 @@ +# `panic_color_errors` + +This feature has no tracking issue yet. + +------------------------ + +With this feature enabled, error messages generated during panics are highlighted for improved visibility and quick identification. By employing color highlighting, developers can easily distinguish error messages from other output, making debugging more efficient and intuitive. This is optional and can be toggled on or off using a dedicated function. The default behaviour is to highlight the errors when there's a terminal. diff --git a/tests/ui/feature-gates/feature-gate-panic_color_errors.rs b/tests/ui/feature-gates/feature-gate-panic_color_errors.rs new file mode 100644 index 0000000000000..6c51303731168 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-panic_color_errors.rs @@ -0,0 +1,6 @@ +use std::panic; + +fn main(){ + panic::highlight_errors(Some(true)); + //~^ ERROR E0658 +} diff --git a/tests/ui/feature-gates/feature-gate-panic_color_errors.stderr b/tests/ui/feature-gates/feature-gate-panic_color_errors.stderr new file mode 100644 index 0000000000000..1b4e7dd3ccf5e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-panic_color_errors.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'panic_color_errors' + --> $DIR/feature-gate-panic_color_errors.rs:4:5 + | +LL | panic::highlight_errors(Some(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(panic_color_errors)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.rs b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.rs new file mode 100644 index 0000000000000..8deee33c42e88 --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.rs @@ -0,0 +1,18 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +fn foo(x: u64) { + if x == 0 { + panic!("Oops sometging went wrong"); + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(None); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.run.stderr b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.run.stderr new file mode 100644 index 0000000000000..11bdcf8c2966b --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_default.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/explicit_panicking_with_backtrace_highlight_errors_default.rs:9:9: +Oops sometging went wrong +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.rs b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.rs new file mode 100644 index 0000000000000..e384fc52071e9 --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.rs @@ -0,0 +1,18 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +fn foo(x: u64) { + if x == 0 { + panic!("Oops sometging went wrong"); + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(Some(false)); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.run.stderr b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.run.stderr new file mode 100644 index 0000000000000..b7f3a0aaa0b1c --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_off.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/explicit_panicking_with_backtrace_highlight_errors_off.rs:9:9: +Oops sometging went wrong +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.rs b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.rs new file mode 100644 index 0000000000000..a88dc43cf5460 --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.rs @@ -0,0 +1,18 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +fn foo(x: u64) { + if x == 0 { + panic!("Oops sometging went wrong"); + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(Some(true)); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.run.stderr b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.run.stderr new file mode 100644 index 0000000000000..b0ab6e2c2589a --- /dev/null +++ b/tests/ui/panics/panic_color_errors/explicit_panicking_with_backtrace_highlight_errors_on.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/explicit_panicking_with_backtrace_highlight_errors_on.rs:9:9: +Oops sometging went wrong +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.rs b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.rs new file mode 100644 index 0000000000000..6b811c9183b04 --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.rs @@ -0,0 +1,23 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +static mut I: [u64; 2] = [0; 2]; + +fn foo(x: u64) { + if x == 0 { + unsafe{ + let j = 12; + I[j] = 0; + } + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(None); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.run.stderr b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.run.stderr new file mode 100644 index 0000000000000..1dabd42d9c91e --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_default.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/forced_error_panicking_highlight_errors_default.rs:13:13: +index out of bounds: the len is 2 but the index is 12 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.rs b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.rs new file mode 100644 index 0000000000000..194781faf0b5b --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.rs @@ -0,0 +1,23 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +static mut I: [u64; 2] = [0; 2]; + +fn foo(x: u64) { + if x == 0 { + unsafe{ + let j = 12; + I[j] = 0; + } + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(Some(false)); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.run.stderr b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.run.stderr new file mode 100644 index 0000000000000..768e24a402feb --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_off.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/forced_error_panicking_highlight_errors_off.rs:13:13: +index out of bounds: the len is 2 but the index is 12 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.rs b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.rs new file mode 100644 index 0000000000000..2b1b772916acc --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.rs @@ -0,0 +1,23 @@ +#![feature(panic_color_errors)] + +//@ run-fail +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 + +static mut I: [u64; 2] = [0; 2]; + +fn foo(x: u64) { + if x == 0 { + unsafe{ + let j = 12; + I[j] = 0; + } + } else { + foo(x-1); + } +} + +fn main() { + std::panic::highlight_errors(Some(true)); + foo(100); +} diff --git a/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.run.stderr b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.run.stderr new file mode 100644 index 0000000000000..527029f2e151a --- /dev/null +++ b/tests/ui/panics/panic_color_errors/forced_error_panicking_highlight_errors_on.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at $DIR/forced_error_panicking_highlight_errors_on.rs:13:13: +index out of bounds: the len is 2 but the index is 12 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace