From 0df6e3394985270c6261cff89f34c922fb4cc870 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sat, 3 Apr 2021 02:51:00 +0200 Subject: [PATCH 01/11] Add assertion details to panic info. The assertion details are added as a new enum field, allowing for future extensions with different information for other sources of panics. For example, `.unwrap()` could extend the enum to store a `&dyn Error` in the panic info. The panic handler in `std` passes the additional info unmodified to the panic hook. --- library/core/src/macros/mod.rs | 38 ++++++++++++-- library/core/src/panic.rs | 24 ++++++++- library/core/src/panic/assert_info.rs | 52 +++++++++++++++++++ library/core/src/panic/extra_info.rs | 6 +++ library/core/src/panic/panic_info.rs | 39 +++++++++++++- library/core/src/panicking.rs | 75 ++++++++++++++++++++------- library/std/src/panicking.rs | 16 ++++-- 7 files changed, 222 insertions(+), 28 deletions(-) create mode 100644 library/core/src/panic/assert_info.rs create mode 100644 library/core/src/panic/extra_info.rs diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5b3e988caa506..b6969498aafd5 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -41,7 +41,14 @@ macro_rules! assert_eq { // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. - $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None); + $crate::panicking::assert_failed( + kind, + $crate::stringify!($left), + &*left_val, + $crate::stringify!($right), + &*right_val, + $crate::option::Option::None, + ); } } } @@ -54,7 +61,14 @@ macro_rules! assert_eq { // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. - $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+))); + $crate::panicking::assert_failed( + kind, + $crate::stringify!($left), + &*left_val, + $crate::stringify!($right), + &*right_val, + $crate::option::Option::Some($crate::format_args!($($arg)+)), + ); } } } @@ -90,7 +104,14 @@ macro_rules! assert_ne { // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. - $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None); + $crate::panicking::assert_failed( + kind, + $crate::stringify!($left), + &*left_val, + $crate::stringify!($right), + &*right_val, + $crate::option::Option::None, + ); } } } @@ -103,7 +124,14 @@ macro_rules! assert_ne { // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. - $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+))); + $crate::panicking::assert_failed( + kind, + $crate::stringify!($left), + &*left_val, + $crate::stringify!($right), + &*right_val, + $crate::option::Option::Some($crate::format_args!($($arg)+)), + ); } } } @@ -145,6 +173,7 @@ pub macro assert_matches { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( + $crate::stringify!($left), left_val, $crate::stringify!($($pattern)|+ $(if $guard)?), $crate::option::Option::None @@ -157,6 +186,7 @@ pub macro assert_matches { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( + $crate::stringify!($left), left_val, $crate::stringify!($($pattern)|+ $(if $guard)?), $crate::option::Option::Some($crate::format_args!($($arg)+)) diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 7a8b04d6f3c13..c301bfad69741 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -5,6 +5,20 @@ mod location; mod panic_info; mod unwind_safe; +#[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" +)] +#[doc(hidden)] +pub mod assert_info; +#[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" +)] +#[doc(hidden)] +pub mod extra_info; use crate::any::Any; @@ -36,7 +50,10 @@ pub macro panic_2015 { $crate::panicking::panic_display(&$arg) ), ($fmt:expr, $($arg:tt)+) => ( - $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) + $crate::panicking::panic_fmt( + $crate::const_format_args!($fmt, $($arg)+), + $crate::option::Option::None, + ) ), } @@ -54,7 +71,10 @@ pub macro panic_2021 { $crate::panicking::panic_display(&$arg) ), ($($t:tt)+) => ( - $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) + $crate::panicking::panic_fmt( + $crate::const_format_args!($($t)+), + $crate::option::Option::None, + ) ), } diff --git a/library/core/src/panic/assert_info.rs b/library/core/src/panic/assert_info.rs new file mode 100644 index 0000000000000..1bc5e42141a03 --- /dev/null +++ b/library/core/src/panic/assert_info.rs @@ -0,0 +1,52 @@ +use crate::fmt::Debug; + +/// Information about a failed assertion. +#[derive(Debug)] +pub struct AssertInfo<'a> { + /// The assertion that failed. + pub assertion: Assertion<'a>, + /// Optional additional message to include in the failure report. + pub message: Option>, +} + +#[derive(Debug)] +pub enum Assertion<'a> { + /// The assertion is a boolean assertion. + Bool(BoolAssertion), + /// The assertion is a binary comparison assertion. + Binary(BinaryAssertion<'a>), +} + +/// Information about a failed boolean assertion. +#[derive(Debug)] +pub struct BoolAssertion { + /// The expression that was evaluated. + pub expr: &'static str, +} + +/// Information about a failed binary comparison assertion. +#[derive(Debug)] +pub struct BinaryAssertion<'a> { + /// The operator used to compare left and right. + pub op: &'static str, + /// The left expression as string. + pub left_expr: &'static str, + /// The right expression as string. + pub right_expr: &'static str, + /// The value of the left expression. + pub left_val: &'a dyn Debug, + /// The value of the right expression. + pub right_val: &'a dyn Debug, +} + +impl<'a> From for Assertion<'a> { + fn from(other: BoolAssertion) -> Self { + Self::Bool(other) + } +} + +impl<'a> From> for Assertion<'a> { + fn from(other: BinaryAssertion<'a>) -> Self { + Self::Binary(other) + } +} diff --git a/library/core/src/panic/extra_info.rs b/library/core/src/panic/extra_info.rs new file mode 100644 index 0000000000000..98d95d83e4581 --- /dev/null +++ b/library/core/src/panic/extra_info.rs @@ -0,0 +1,6 @@ +use crate::panic::assert_info::AssertInfo; + +#[derive(Debug, Copy, Clone)] +pub enum ExtraInfo<'a> { + AssertInfo(&'a AssertInfo<'a>), +} diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 649bc3e44ad21..22b5b3351da3a 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -1,5 +1,7 @@ use crate::any::Any; use crate::fmt; +use crate::panic::assert_info::AssertInfo; +use crate::panic::extra_info::ExtraInfo; use crate::panic::Location; /// A struct providing information about a panic. @@ -31,6 +33,7 @@ pub struct PanicInfo<'a> { payload: &'a (dyn Any + Send), message: Option<&'a fmt::Arguments<'a>>, location: &'a Location<'a>, + extra_info: Option>, } impl<'a> PanicInfo<'a> { @@ -46,7 +49,7 @@ impl<'a> PanicInfo<'a> { location: &'a Location<'a>, ) -> Self { struct NoPayload; - PanicInfo { location, message, payload: &NoPayload } + PanicInfo { location, message, payload: &NoPayload, extra_info: None } } #[unstable( @@ -124,6 +127,40 @@ impl<'a> PanicInfo<'a> { // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. Some(&self.location) } + + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + #[doc(hidden)] + #[inline] + pub fn set_extra_info(&mut self, info: Option>) { + self.extra_info = info; + } + + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + #[doc(hidden)] + #[inline] + pub fn extra_info(&self) -> Option> { + self.extra_info + } + + /// Get the information about the assertion that caused the panic. + /// + /// Returns `None` if the panic was not caused by an assertion. + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + pub fn assert_info(&self) -> Option<&AssertInfo<'_>> { + if let Some(ExtraInfo::AssertInfo(x)) = &self.extra_info { Some(x) } else { None } + } } #[stable(feature = "panic_hook_display", since = "1.26.0")] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a12447acf7ec3..b1d8ea1ac1c66 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -27,6 +27,8 @@ )] use crate::fmt; +use crate::panic::assert_info::{AssertInfo, Assertion, BinaryAssertion}; +use crate::panic::extra_info::ExtraInfo; use crate::panic::{Location, PanicInfo}; /// The underlying implementation of libcore's `panic!` macro when no formatting is used. @@ -47,14 +49,14 @@ pub fn panic(expr: &'static str) -> ! { // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), None); } #[inline] #[track_caller] #[lang = "panic_str"] // needed for const-evaluated panics pub fn panic_str(expr: &str) -> ! { - panic_fmt(format_args!("{}", expr)); + panic_fmt(format_args!("{}", expr), None); } #[inline] @@ -89,7 +91,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics -pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { +pub fn panic_fmt(fmt: fmt::Arguments<'_>, extra_info: Option>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -101,7 +103,8 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { fn panic_impl(pi: &PanicInfo<'_>) -> !; } - let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller()); + let mut pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller()); + pi.set_extra_info(extra_info); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } @@ -134,15 +137,17 @@ pub enum AssertKind { #[doc(hidden)] pub fn assert_failed( kind: AssertKind, - left: &T, - right: &U, + left_expr: &'static str, + left_val: &T, + right_expr: &'static str, + right_val: &U, args: Option>, ) -> ! where T: fmt::Debug + ?Sized, U: fmt::Debug + ?Sized, { - assert_failed_inner(kind, &left, &right, args) + assert_failed_inner(kind, left_expr, &left_val, right_expr, &right_val, args) } /// Internal function for `assert_match!` @@ -150,8 +155,9 @@ where #[track_caller] #[doc(hidden)] pub fn assert_matches_failed( - left: &T, - right: &str, + left_expr: &'static str, + left_val: &T, + right_pattern: &'static str, args: Option>, ) -> ! { // Use the Display implementation to display the pattern. @@ -161,15 +167,24 @@ pub fn assert_matches_failed( fmt::Display::fmt(self.0, f) } } - assert_failed_inner(AssertKind::Match, &left, &Pattern(right), args); + assert_failed_inner( + AssertKind::Match, + left_expr, + &left_val, + right_pattern, + &Pattern(right_pattern), + args, + ); } /// Non-generic version of the above functions, to avoid code bloat. #[track_caller] fn assert_failed_inner( kind: AssertKind, - left: &dyn fmt::Debug, - right: &dyn fmt::Debug, + left_expr: &'static str, + left_val: &dyn fmt::Debug, + right_expr: &'static str, + right_val: &dyn fmt::Debug, args: Option>, ) -> ! { let op = match kind { @@ -179,17 +194,41 @@ fn assert_failed_inner( }; match args { - Some(args) => panic!( - r#"assertion failed: `(left {} right)` + Some(args) => panic_fmt( + format_args!( + r#"assertion failed: `(left {} right)` left: `{:?}`, right: `{:?}`: {}"#, - op, left, right, args + op, left_val, right_val, args + ), + Some(ExtraInfo::AssertInfo(&AssertInfo { + assertion: Assertion::Binary(BinaryAssertion { + op, + left_expr, + right_expr, + left_val, + right_val, + }), + message: Some(args), + })), ), - None => panic!( - r#"assertion failed: `(left {} right)` + None => panic_fmt( + format_args!( + r#"assertion failed: `(left {} right)` left: `{:?}`, right: `{:?}`"#, - op, left, right, + op, left_val, right_val + ), + Some(ExtraInfo::AssertInfo(&AssertInfo { + assertion: Assertion::Binary(BinaryAssertion { + op, + left_expr, + right_expr, + left_val, + right_val, + }), + message: None, + })), ), } } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 56646b72dd54f..3243f8a3aa7b3 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -9,6 +9,7 @@ #![deny(unsafe_op_in_unsafe_fn)] +use core::panic::extra_info::ExtraInfo; use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; @@ -492,11 +493,17 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some + crate::sys_common::backtrace::__rust_end_short_backtrace(move || { if let Some(msg) = msg.as_str() { - rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc); + rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.extra_info()); } else { - rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + loc, + info.extra_info(), + ); } }) } @@ -519,7 +526,7 @@ pub fn begin_panic(msg: M) -> ! { let loc = Location::caller(); return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, None) }); struct PanicPayload { @@ -564,6 +571,7 @@ fn rust_panic_with_hook( payload: &mut dyn BoxMeUp, message: Option<&fmt::Arguments<'_>>, location: &Location<'_>, + extra_info: Option>, ) -> ! { let (must_abort, panics) = panic_count::increase(); @@ -599,10 +607,12 @@ fn rust_panic_with_hook( Hook::Default if panic_output().is_none() => {} Hook::Default => { info.set_payload(payload.get()); + info.set_extra_info(extra_info); default_hook(&info); } Hook::Custom(ptr) => { info.set_payload(payload.get()); + info.set_extra_info(extra_info); (*ptr)(&info); } }; From 0994b8aaeaeeb991b99b5f6df2a4728b48b063cb Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Thu, 12 Nov 2020 16:00:02 +0100 Subject: [PATCH 02/11] Add function to test if terminal supports ANSI color codes. --- library/test/src/term.rs | 6 ++++ library/test/src/term/terminfo/mod.rs | 4 +++ library/test/src/term/win.rs | 42 ++++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/library/test/src/term.rs b/library/test/src/term.rs index b256ab7b8f828..d9a53ea9090a8 100644 --- a/library/test/src/term.rs +++ b/library/test/src/term.rs @@ -71,6 +71,12 @@ pub trait Terminal: Write { /// if there was an I/O error. fn fg(&mut self, color: color::Color) -> io::Result; + /// Returns `true` if the terminal supports ANSI color codes. + /// + /// ANSI color codes can be buffered along with the output, + /// but not all Windows terminals support them. + fn supports_ansi_colors(&self) -> bool; + /// Resets all terminal attributes and colors to their defaults. /// /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs index 694473f52c1a7..25c006fb8c2ea 100644 --- a/library/test/src/term/terminfo/mod.rs +++ b/library/test/src/term/terminfo/mod.rs @@ -125,6 +125,10 @@ impl Terminal for TerminfoTerminal { Ok(false) } + fn supports_ansi_colors(&self) -> bool { + self.num_colors > 0 + } + fn reset(&mut self) -> io::Result { // are there any terminals that have color/attrs and not sgr0? // Try falling back to sgr, then op diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs index 4bdbd6ee75f52..d033774d10779 100644 --- a/library/test/src/term/win.rs +++ b/library/test/src/term/win.rs @@ -53,6 +53,7 @@ struct CONSOLE_SCREEN_BUFFER_INFO { #[link(name = "kernel32")] extern "system" { fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL; + fn GetConsoleMode(handle: HANDLE, mode: *mut DWORD) -> BOOL; fn GetStdHandle(which: DWORD) -> HANDLE; fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL; } @@ -91,6 +92,21 @@ fn bits_to_color(bits: u16) -> color::Color { color | (u32::from(bits) & 0x8) // copy the hi-intensity bit } +fn get_stdout_handle() -> HANDLE { + unsafe { + // Magic -11 means stdout, from + // https://docs.microsoft.com/en-us/windows/console/getstdhandle + // + // You may be wondering, "but what about stderr?", and the answer + // to that is that setting terminal attributes on the stdout + // handle also sets them for stderr, since they go to the same + // terminal! Admittedly, this is fragile, since stderr could be + // redirected to a different console. This is good enough for + // rustc though. See #13400. + GetStdHandle(-11i32 as DWORD) + } +} + impl WinConsole { fn apply(&mut self) { let _unused = self.buf.flush(); @@ -98,17 +114,8 @@ impl WinConsole { accum |= color_to_bits(self.foreground); accum |= color_to_bits(self.background) << 4; + let out = get_stdout_handle(); unsafe { - // Magic -11 means stdout, from - // https://docs.microsoft.com/en-us/windows/console/getstdhandle - // - // You may be wondering, "but what about stderr?", and the answer - // to that is that setting terminal attributes on the stdout - // handle also sets them for stderr, since they go to the same - // terminal! Admittedly, this is fragile, since stderr could be - // redirected to a different console. This is good enough for - // rustc though. See #13400. - let out = GetStdHandle(-11i32 as DWORD); SetConsoleTextAttribute(out, accum); } } @@ -160,6 +167,21 @@ impl Terminal for WinConsole { Ok(true) } + fn supports_ansi_colors(&self) -> bool { + // From https://docs.microsoft.com/en-us/windows/console/getconsolemode + const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004; + + let stdout = get_stdout_handle(); + let mut mode: DWORD = 0; + unsafe { + if GetConsoleMode(stdout, &mut mode) != 0 { + mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 + } else { + false + } + } + } + fn reset(&mut self) -> io::Result { self.foreground = self.def_foreground; self.background = self.def_background; From d57b2da1f124d9673abdffdbb21bfdb8dcc1918c Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Mon, 9 Nov 2020 23:57:46 +0100 Subject: [PATCH 03/11] Pretty-print assertion failures in `test` with unstable flag. --- library/test/src/cli.rs | 9 ++ library/test/src/console.rs | 26 +++++ library/test/src/lib.rs | 3 + library/test/src/pretty_print_assertion.rs | 110 +++++++++++++++++++++ library/test/src/tests.rs | 1 + src/tools/compiletest/src/main.rs | 1 + 6 files changed, 150 insertions(+) create mode 100644 library/test/src/pretty_print_assertion.rs diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index cb40b4e965b2a..39b8f0928dd33 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -23,6 +23,7 @@ pub struct TestOpts { pub format: OutputFormat, pub shuffle: bool, pub shuffle_seed: Option, + pub pretty_print_assertions: bool, pub test_threads: Option, pub skip: Vec, pub time_options: Option, @@ -147,6 +148,11 @@ fn optgroups() -> getopts::Options { "shuffle-seed", "Run tests in random order; seed the random number generator with SEED", "SEED", + ) + .optflag( + "", + "pretty-print-assertions", + "Pretty-print assertion failures using experimental formatting.", ); opts } @@ -276,6 +282,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { let test_threads = get_test_threads(&matches)?; let color = get_color_config(&matches)?; let format = get_format(&matches, quiet, allow_unstable)?; + let pretty_print_assertions = + unstable_optflag!(matches, allow_unstable, "pretty-print-assertions"); let options = Options::new().display_output(matches.opt_present("show-output")); @@ -294,6 +302,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { format, shuffle, shuffle_seed, + pretty_print_assertions, test_threads, skip, time_options, diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 11c5ab48ed3e8..55e07a589bf6b 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -13,6 +13,7 @@ use super::{ formatters::{JsonFormatter, JunitFormatter, OutputFormatter, PrettyFormatter, TerseFormatter}, helpers::{concurrency::get_concurrency, metrics::MetricMap}, options::{Options, OutputFormat}, + pretty_print_assertion::pretty_print_assertion, run_tests, term, test_result::TestResult, time::{TestExecTime, TestSuiteExecTime}, @@ -25,6 +26,16 @@ pub enum OutputLocation { Raw(T), } +impl OutputLocation { + /// Check if the output location supports ANSI color codes. + pub fn supports_ansi_colors(&self) -> bool { + match self { + OutputLocation::Pretty(term) => term.supports_ansi_colors(), + OutputLocation::Raw(_) => false, + } + } +} + impl Write for OutputLocation { fn write(&mut self, buf: &[u8]) -> io::Result { match *self { @@ -251,12 +262,27 @@ fn on_test_event( /// A simple console test runner. /// Runs provided tests reporting process and results to the stdout. +/// +/// If pretty-printing of assertion failures is enabled, this installs a panic hook. pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Result { let output = match term::stdout() { None => OutputLocation::Raw(io::stdout()), Some(t) => OutputLocation::Pretty(t), }; + if opts.pretty_print_assertions { + let panic_hook = std::panic::take_hook(); + let use_color = opts.use_color() && output.supports_ansi_colors(); + std::panic::set_hook(Box::new(move |info| { + if let Some(assert) = info.assert_info() { + let loc = *info.location().unwrap(); + let _ = pretty_print_assertion(assert, loc, use_color); + } else { + panic_hook(info) + } + })); + } + let max_name_len = tests .iter() .max_by_key(|t| len_if_padded(*t)) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 99d951d8016bb..1f2fbd733244e 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -23,10 +23,12 @@ #![feature(libc)] #![feature(rustc_private)] #![feature(nll)] +#![feature(core_panic)] #![feature(available_parallelism)] #![feature(bench_black_box)] #![feature(internal_output_capture)] #![feature(panic_unwind)] +#![feature(panic_internals)] #![feature(staged_api)] #![feature(termination_trait_lib)] #![feature(test)] @@ -79,6 +81,7 @@ mod event; mod formatters; mod helpers; mod options; +mod pretty_print_assertion; pub mod stats; mod term; mod test_result; diff --git a/library/test/src/pretty_print_assertion.rs b/library/test/src/pretty_print_assertion.rs new file mode 100644 index 0000000000000..90a0d3181c78a --- /dev/null +++ b/library/test/src/pretty_print_assertion.rs @@ -0,0 +1,110 @@ +use core::panic::assert_info::{AssertInfo, Assertion, BinaryAssertion, BoolAssertion}; +use core::panic::Location; + +const RED: &str = "\x1b[31m"; +const YELLOW: &str = "\x1b[33m"; +const BLUE: &str = "\x1b[34m"; +const CYAN: &str = "\x1b[36m"; +const BOLD: &str = "\x1b[1m"; +const RESET: &str = "\x1b[0m"; + +/// Print an assertion to standard error. +/// +/// If `ansi_colors` is true, this function unconditionally prints ANSI color codes. +/// It should only be set to true only if it is known that the terminal supports it. +pub fn pretty_print_assertion(assert: &AssertInfo<'_>, loc: Location<'_>, ansi_colors: bool) { + if ansi_colors { + print_pretty_header(loc); + match &assert.assertion { + Assertion::Bool(assert) => print_pretty_bool_assertion(assert), + Assertion::Binary(assert) => print_pretty_binary_assertion(assert), + } + if let Some(msg) = &assert.message { + print_pretty_message(msg); + } + } else { + print_plain_header(loc); + match &assert.assertion { + Assertion::Bool(assert) => print_plain_bool_assertion(assert), + Assertion::Binary(assert) => print_plain_binary_assertion(assert), + } + if let Some(msg) = &assert.message { + print_plain_message(msg); + } + } +} + +fn print_plain_header(loc: Location<'_>) { + eprintln!("Assertion failed at {}:{}:{}:", loc.file(), loc.line(), loc.column()) +} + +fn print_pretty_header(loc: Location<'_>) { + eprintln!( + "{bold}{red}Assertion failed{reset} at {bold}{file}{reset}:{line}:{col}:", + red = RED, + bold = BOLD, + reset = RESET, + file = loc.file(), + line = loc.line(), + col = loc.column(), + ); +} + +fn print_plain_bool_assertion(assert: &BoolAssertion) { + eprintln!("Assertion:\n {}", assert.expr); + eprintln!("Expansion:\n false"); +} + +fn print_pretty_bool_assertion(assert: &BoolAssertion) { + eprintln!( + "{bold}Assertion:{reset}\n {cyan}{expr}{reset}", + cyan = CYAN, + reset = RESET, + bold = BOLD, + expr = assert.expr, + ); + eprintln!( + "{bold}Expansion:{reset}\n {cyan}false{reset}", + cyan = CYAN, + bold = BOLD, + reset = RESET, + ); +} + +fn print_plain_binary_assertion(assert: &BinaryAssertion<'_>) { + eprintln!("Assertion:\n {} {} {}", assert.left_expr, assert.op, assert.right_expr); + eprintln!("Expansion:\n {:?} {} {:?}", assert.left_val, assert.op, assert.right_val); +} + +fn print_pretty_binary_assertion(assert: &BinaryAssertion<'_>) { + eprintln!( + "{bold}Assertion:{reset}\n {cyan}{left} {bold}{blue}{op}{reset} {yellow}{right}{reset}", + cyan = CYAN, + blue = BLUE, + yellow = YELLOW, + bold = BOLD, + reset = RESET, + left = assert.left_expr, + op = assert.op, + right = assert.right_expr, + ); + eprintln!( + "{bold}Expansion:{reset}\n {cyan}{left:?} {bold}{blue}{op}{reset} {yellow}{right:?}{reset}", + cyan = CYAN, + blue = BLUE, + yellow = YELLOW, + bold = BOLD, + reset = RESET, + left = assert.left_val, + op = assert.op, + right = assert.right_val, + ); +} + +fn print_plain_message(message: &std::fmt::Arguments<'_>) { + eprintln!("Message:\n {}", message); +} + +fn print_pretty_message(message: &std::fmt::Arguments<'_>) { + eprintln!("{bold}Message:{reset}\n {msg}", bold = BOLD, reset = RESET, msg = message,); +} diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 718613895dee4..d5dbf521c2a81 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -47,6 +47,7 @@ impl TestOpts { format: OutputFormat::Pretty, shuffle: false, shuffle_seed: None, + pretty_print_assertions: false, test_threads: None, skip: vec![], time_options: None, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 87aba8c5d32bf..a93b68869b367 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -508,6 +508,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { color: config.color, shuffle: false, shuffle_seed: None, + pretty_print_assertions: false, test_threads: None, skip: vec![], list: false, From 9596fcef7ac714be5ed7148df6a60f7358c89129 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Thu, 12 Nov 2020 23:18:48 +0100 Subject: [PATCH 04/11] Mark panic::ExtraInfo as non-exhaustive. Co-authored-by: Mara Bos --- library/core/src/panic/extra_info.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/panic/extra_info.rs b/library/core/src/panic/extra_info.rs index 98d95d83e4581..a212aea992a52 100644 --- a/library/core/src/panic/extra_info.rs +++ b/library/core/src/panic/extra_info.rs @@ -1,6 +1,7 @@ use crate::panic::assert_info::AssertInfo; #[derive(Debug, Copy, Clone)] +#[non_exhaustive] pub enum ExtraInfo<'a> { AssertInfo(&'a AssertInfo<'a>), } From 7f8140e64aa84a24edf63ba0787bfa7ed70e107c Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Fri, 13 Nov 2020 12:15:02 +0100 Subject: [PATCH 05/11] Add more documentation to `AssertInfo` and related types. --- library/core/src/panic/assert_info.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/library/core/src/panic/assert_info.rs b/library/core/src/panic/assert_info.rs index 1bc5e42141a03..04fcd0e3ad552 100644 --- a/library/core/src/panic/assert_info.rs +++ b/library/core/src/panic/assert_info.rs @@ -9,22 +9,41 @@ pub struct AssertInfo<'a> { pub message: Option>, } +/// Details about the expression that failed an assertion. #[derive(Debug)] pub enum Assertion<'a> { - /// The assertion is a boolean assertion. + /// The failed assertion is a boolean expression. + /// + /// This variant is only used for expressions that can't be described more specifically + /// by another variant. Bool(BoolAssertion), - /// The assertion is a binary comparison assertion. + + /// The failed assertion is a binary comparison expression. + /// + /// This is used by `assert_eq!()`, `assert_ne!()` and expressions like + /// `assert!(x > 10)`. Binary(BinaryAssertion<'a>), } /// Information about a failed boolean assertion. +/// +/// The expression was asserted to be true, but it evaluated to false. +/// +/// This struct is only used for assertion failures that can't be described more specifically +/// by another assertion type. #[derive(Debug)] pub struct BoolAssertion { - /// The expression that was evaluated. + /// The expression that was evaluated to false. pub expr: &'static str, } /// Information about a failed binary comparison assertion. +/// +/// The left expression was compared with the right expression using `op`, +/// and the comparison evaluted to false. +/// +/// This struct is used for `assert_eq!()`, `assert_ne!()` and expressions like +/// `assert!(x > 10)`. #[derive(Debug)] pub struct BinaryAssertion<'a> { /// The operator used to compare left and right. From 5886466d616f501bb26453065436c0d5d8d0e19f Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Fri, 13 Nov 2020 12:19:40 +0100 Subject: [PATCH 06/11] Replace get_stdout_handle() with io::stdout().as_raw_handle(). --- library/test/src/term/win.rs | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs index d033774d10779..445b070bbd02e 100644 --- a/library/test/src/term/win.rs +++ b/library/test/src/term/win.rs @@ -4,6 +4,7 @@ use std::io; use std::io::prelude::*; +use std::os::windows::{io::AsRawHandle, raw::HANDLE}; use super::color; use super::Terminal; @@ -21,7 +22,6 @@ type SHORT = i16; type WORD = u16; type DWORD = u32; type BOOL = i32; -type HANDLE = *mut u8; #[allow(non_snake_case)] #[repr(C)] @@ -54,7 +54,6 @@ struct CONSOLE_SCREEN_BUFFER_INFO { extern "system" { fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL; fn GetConsoleMode(handle: HANDLE, mode: *mut DWORD) -> BOOL; - fn GetStdHandle(which: DWORD) -> HANDLE; fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL; } @@ -92,21 +91,6 @@ fn bits_to_color(bits: u16) -> color::Color { color | (u32::from(bits) & 0x8) // copy the hi-intensity bit } -fn get_stdout_handle() -> HANDLE { - unsafe { - // Magic -11 means stdout, from - // https://docs.microsoft.com/en-us/windows/console/getstdhandle - // - // You may be wondering, "but what about stderr?", and the answer - // to that is that setting terminal attributes on the stdout - // handle also sets them for stderr, since they go to the same - // terminal! Admittedly, this is fragile, since stderr could be - // redirected to a different console. This is good enough for - // rustc though. See #13400. - GetStdHandle(-11i32 as DWORD) - } -} - impl WinConsole { fn apply(&mut self) { let _unused = self.buf.flush(); @@ -114,7 +98,7 @@ impl WinConsole { accum |= color_to_bits(self.foreground); accum |= color_to_bits(self.background) << 4; - let out = get_stdout_handle(); + let out = std::io::stdout().as_raw_handle(); unsafe { SetConsoleTextAttribute(out, accum); } @@ -126,11 +110,10 @@ impl WinConsole { let fg; let bg; + let stdout = std::io::stdout().as_raw_handle(); unsafe { let mut buffer_info = MaybeUninit::::uninit(); - if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), buffer_info.as_mut_ptr()) - != 0 - { + if GetConsoleScreenBufferInfo(stdout, buffer_info.as_mut_ptr()) != 0 { let buffer_info = buffer_info.assume_init(); fg = bits_to_color(buffer_info.wAttributes); bg = bits_to_color(buffer_info.wAttributes >> 4); @@ -171,7 +154,7 @@ impl Terminal for WinConsole { // From https://docs.microsoft.com/en-us/windows/console/getconsolemode const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004; - let stdout = get_stdout_handle(); + let stdout = std::io::stdout().as_raw_handle(); let mut mode: DWORD = 0; unsafe { if GetConsoleMode(stdout, &mut mode) != 0 { From 3ff9a91d73a9dc08be927cb72b9023be0f59fd8a Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sun, 24 Jan 2021 00:17:03 +0100 Subject: [PATCH 07/11] Include macro name in pretty printed assertion. And use a comma to separate arguments of `assert_eq` and `assert_ne`. This has two advantages: * The printed text more closely matches the actual source code. * It avoids changing the meaning of $left == $right if $left or $right contain operators themselves. --- library/core/src/panic/assert_info.rs | 2 + library/core/src/panicking.rs | 10 +- library/test/src/pretty_print_assertion.rs | 142 +++++++++++++++------ 3 files changed, 108 insertions(+), 46 deletions(-) diff --git a/library/core/src/panic/assert_info.rs b/library/core/src/panic/assert_info.rs index 04fcd0e3ad552..f60d5e7234511 100644 --- a/library/core/src/panic/assert_info.rs +++ b/library/core/src/panic/assert_info.rs @@ -5,6 +5,8 @@ use crate::fmt::Debug; pub struct AssertInfo<'a> { /// The assertion that failed. pub assertion: Assertion<'a>, + /// The name of the macro that triggered the panic. + pub macro_name: &'static str, /// Optional additional message to include in the failure report. pub message: Option>, } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index b1d8ea1ac1c66..6aef1d1325851 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -187,10 +187,10 @@ fn assert_failed_inner( right_val: &dyn fmt::Debug, args: Option>, ) -> ! { - let op = match kind { - AssertKind::Eq => "==", - AssertKind::Ne => "!=", - AssertKind::Match => "matches", + let (op, macro_name) = match kind { + AssertKind::Eq => ("==", "assert_eq"), + AssertKind::Ne => ("!=", "assert_ne"), + AssertKind::Match => ("matches", "assert_matches"), }; match args { @@ -209,6 +209,7 @@ fn assert_failed_inner( left_val, right_val, }), + macro_name, message: Some(args), })), ), @@ -227,6 +228,7 @@ fn assert_failed_inner( left_val, right_val, }), + macro_name, message: None, })), ), diff --git a/library/test/src/pretty_print_assertion.rs b/library/test/src/pretty_print_assertion.rs index 90a0d3181c78a..24fdfba9e4936 100644 --- a/library/test/src/pretty_print_assertion.rs +++ b/library/test/src/pretty_print_assertion.rs @@ -4,6 +4,7 @@ use core::panic::Location; const RED: &str = "\x1b[31m"; const YELLOW: &str = "\x1b[33m"; const BLUE: &str = "\x1b[34m"; +const MAGENTA: &str = "\x1b[35m"; const CYAN: &str = "\x1b[36m"; const BOLD: &str = "\x1b[1m"; const RESET: &str = "\x1b[0m"; @@ -13,11 +14,12 @@ const RESET: &str = "\x1b[0m"; /// If `ansi_colors` is true, this function unconditionally prints ANSI color codes. /// It should only be set to true only if it is known that the terminal supports it. pub fn pretty_print_assertion(assert: &AssertInfo<'_>, loc: Location<'_>, ansi_colors: bool) { + let macro_name = assert.macro_name; if ansi_colors { print_pretty_header(loc); match &assert.assertion { - Assertion::Bool(assert) => print_pretty_bool_assertion(assert), - Assertion::Binary(assert) => print_pretty_binary_assertion(assert), + Assertion::Bool(assert) => print_pretty_bool_assertion(macro_name, assert), + Assertion::Binary(assert) => print_pretty_binary_assertion(macro_name, assert), } if let Some(msg) = &assert.message { print_pretty_message(msg); @@ -25,8 +27,8 @@ pub fn pretty_print_assertion(assert: &AssertInfo<'_>, loc: Location<'_>, ansi_c } else { print_plain_header(loc); match &assert.assertion { - Assertion::Bool(assert) => print_plain_bool_assertion(assert), - Assertion::Binary(assert) => print_plain_binary_assertion(assert), + Assertion::Bool(assert) => print_plain_bool_assertion(macro_name, assert), + Assertion::Binary(assert) => print_plain_binary_assertion(macro_name, assert), } if let Some(msg) = &assert.message { print_plain_message(msg); @@ -50,55 +52,111 @@ fn print_pretty_header(loc: Location<'_>) { ); } -fn print_plain_bool_assertion(assert: &BoolAssertion) { - eprintln!("Assertion:\n {}", assert.expr); - eprintln!("Expansion:\n false"); +fn print_plain_bool_assertion(macro_name: &'static str, assert: &BoolAssertion) { + eprint!( + concat!( + "Assertion:\n", + " {macro_name}!( {expr} )\n", + "Expansion:\n", + " {macro_name}!( false )\n", + ), + macro_name = macro_name, + expr = assert.expr, + ) } -fn print_pretty_bool_assertion(assert: &BoolAssertion) { - eprintln!( - "{bold}Assertion:{reset}\n {cyan}{expr}{reset}", +fn print_pretty_bool_assertion(macro_name: &'static str, assert: &BoolAssertion) { + eprint!( + concat!( + "{bold}Assertion:{reset}\n", + " {magenta}{macro_name}!( {cyan}{expr} {magenta}){reset}\n", + "{bold}Expansion:{reset}\n", + " {magenta}{macro_name}!( {cyan}false {magenta}){reset}\n", + ), + magenta = MAGENTA, cyan = CYAN, reset = RESET, bold = BOLD, + macro_name = macro_name, expr = assert.expr, ); - eprintln!( - "{bold}Expansion:{reset}\n {cyan}false{reset}", - cyan = CYAN, - bold = BOLD, - reset = RESET, - ); } -fn print_plain_binary_assertion(assert: &BinaryAssertion<'_>) { - eprintln!("Assertion:\n {} {} {}", assert.left_expr, assert.op, assert.right_expr); - eprintln!("Expansion:\n {:?} {} {:?}", assert.left_val, assert.op, assert.right_val); +fn print_plain_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { + if macro_name == "assert_eq" || macro_name == "assert_ne" { + eprint!( + concat!( + "Assertion:\n", + " {macro_name}!( {left_expr}, {right_expr} )\n", + "Expansion:\n", + " {macro_name}!( {left_val:?}, {right_val:?} )\n", + ), + macro_name = macro_name, + left_expr = assert.left_expr, + right_expr = assert.right_expr, + left_val = assert.left_val, + right_val = assert.right_val, + ); + } else { + eprint!( + concat!( + "Assertion:\n", + " {macro_name}!( {left_expr} {op} {right_expr} )\n", + "Expansion:\n", + " {macro_name}!( {left_val:?} {op} {right_val:?} )\n", + ), + macro_name = macro_name, + op = assert.op, + left_expr = assert.left_expr, + right_expr = assert.right_expr, + left_val = assert.left_val, + right_val = assert.right_val, + ); + }; } -fn print_pretty_binary_assertion(assert: &BinaryAssertion<'_>) { - eprintln!( - "{bold}Assertion:{reset}\n {cyan}{left} {bold}{blue}{op}{reset} {yellow}{right}{reset}", - cyan = CYAN, - blue = BLUE, - yellow = YELLOW, - bold = BOLD, - reset = RESET, - left = assert.left_expr, - op = assert.op, - right = assert.right_expr, - ); - eprintln!( - "{bold}Expansion:{reset}\n {cyan}{left:?} {bold}{blue}{op}{reset} {yellow}{right:?}{reset}", - cyan = CYAN, - blue = BLUE, - yellow = YELLOW, - bold = BOLD, - reset = RESET, - left = assert.left_val, - op = assert.op, - right = assert.right_val, - ); +fn print_pretty_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { + if macro_name == "assert_eq" || macro_name == "assert_ne" { + eprint!( + concat!( + "{bold}Assertion:{reset}\n", + " {magenta}{macro_name}!( {cyan}{left_expr}{magenta}, {yellow}{right_expr} {magenta}){reset}\n", + "{bold}Expansion:{reset}\n", + " {magenta}{macro_name}!( {cyan}{left_val:?}{magenta}, {yellow}{right_val:?} {magenta}){reset}\n", + ), + cyan = CYAN, + magenta = MAGENTA, + yellow = YELLOW, + bold = BOLD, + reset = RESET, + macro_name = macro_name, + left_expr = assert.left_expr, + right_expr = assert.right_expr, + left_val = assert.left_val, + right_val = assert.right_val, + ); + } else { + eprint!( + concat!( + "{bold}Assertion:{reset}\n", + " {magenta}{macro_name}!( {cyan}{left_expr} {bold}{blue}{op}{reset} {yellow}{right_expr} {magenta}){reset}\n", + "{bold}Expansion:{reset}\n", + " {magenta}{macro_name}!( {cyan}{left_val:?} {bold}{blue}{op}{reset} {yellow}{right_val:?} {magenta}){reset}\n", + ), + blue = BLUE, + cyan = CYAN, + magenta = MAGENTA, + yellow = YELLOW, + bold = BOLD, + reset = RESET, + macro_name = macro_name, + op = assert.op, + left_expr = assert.left_expr, + right_expr = assert.right_expr, + left_val = assert.left_val, + right_val = assert.right_val, + ); + }; } fn print_plain_message(message: &std::fmt::Arguments<'_>) { From 3b03d3a5261f97c0785498cf0026d031af51ef82 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sat, 3 Apr 2021 14:56:13 +0200 Subject: [PATCH 08/11] Do not show fake operator in pretty-printed assert_matches failure. --- library/test/src/pretty_print_assertion.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/test/src/pretty_print_assertion.rs b/library/test/src/pretty_print_assertion.rs index 24fdfba9e4936..ea446b1dcc375 100644 --- a/library/test/src/pretty_print_assertion.rs +++ b/library/test/src/pretty_print_assertion.rs @@ -83,7 +83,7 @@ fn print_pretty_bool_assertion(macro_name: &'static str, assert: &BoolAssertion) } fn print_plain_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { - if macro_name == "assert_eq" || macro_name == "assert_ne" { + if is_specalized_macro(macro_name) { eprint!( concat!( "Assertion:\n", @@ -116,7 +116,7 @@ fn print_plain_binary_assertion(macro_name: &'static str, assert: &BinaryAsserti } fn print_pretty_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { - if macro_name == "assert_eq" || macro_name == "assert_ne" { + if is_specalized_macro(macro_name) { eprint!( concat!( "{bold}Assertion:{reset}\n", @@ -166,3 +166,9 @@ fn print_plain_message(message: &std::fmt::Arguments<'_>) { fn print_pretty_message(message: &std::fmt::Arguments<'_>) { eprintln!("{bold}Message:{reset}\n {msg}", bold = BOLD, reset = RESET, msg = message,); } + +fn is_specalized_macro(macro_name: &str) -> bool { + // Specialized macros already imply the operator in their name, + // so we print them without repeating the operator. + macro_name == "assert_eq" || macro_name == "assert_neq" || macro_name == "assert_matches" +} From 4b8790794f548c2570b8bddc762eea0ebfd90b13 Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Wed, 20 Oct 2021 21:31:55 +0200 Subject: [PATCH 09/11] Try to improve performance by reducing the size of involved types --- library/core/src/macros/mod.rs | 56 ++++---- library/core/src/panic.rs | 18 +-- library/core/src/panic/assert_info.rs | 112 +++++++++------- library/core/src/panic/extra_info.rs | 7 - library/core/src/panic/panic_description.rs | 27 ++++ library/core/src/panic/panic_info.rs | 57 ++++----- library/core/src/panicking.rs | 109 ++++------------ library/std/src/panicking.rs | 38 +++--- library/test/src/pretty_print_assertion.rs | 134 ++++---------------- 9 files changed, 231 insertions(+), 327 deletions(-) delete mode 100644 library/core/src/panic/extra_info.rs create mode 100644 library/core/src/panic/panic_description.rs diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index b6969498aafd5..c8711f6dd1e01 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -31,21 +31,22 @@ macro_rules! panic { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable(core_panic)] +#[allow_internal_unstable(core_panic, panic_internals)] macro_rules! assert_eq { ($left:expr, $right:expr $(,)?) => ({ match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { - let kind = $crate::panicking::AssertKind::Eq; // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. $crate::panicking::assert_failed( - kind, - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Eq, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($right), + }, &*left_val, - $crate::stringify!($right), &*right_val, $crate::option::Option::None, ); @@ -57,15 +58,16 @@ macro_rules! assert_eq { match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { - let kind = $crate::panicking::AssertKind::Eq; // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. $crate::panicking::assert_failed( - kind, - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Eq, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($right), + }, &*left_val, - $crate::stringify!($right), &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+)), ); @@ -94,21 +96,22 @@ macro_rules! assert_eq { /// ``` #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] -#[allow_internal_unstable(core_panic)] +#[allow_internal_unstable(core_panic, panic_internals)] macro_rules! assert_ne { ($left:expr, $right:expr $(,)?) => ({ match (&$left, &$right) { (left_val, right_val) => { if *left_val == *right_val { - let kind = $crate::panicking::AssertKind::Ne; // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. $crate::panicking::assert_failed( - kind, - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Ne, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($right), + }, &*left_val, - $crate::stringify!($right), &*right_val, $crate::option::Option::None, ); @@ -120,15 +123,16 @@ macro_rules! assert_ne { match (&($left), &($right)) { (left_val, right_val) => { if *left_val == *right_val { - let kind = $crate::panicking::AssertKind::Ne; // The reborrows below are intentional. Without them, the stack slot for the // borrow is initialized even before the values are compared, leading to a // noticeable slow down. $crate::panicking::assert_failed( - kind, - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Ne, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($right), + }, &*left_val, - $crate::stringify!($right), &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+)), ); @@ -165,7 +169,7 @@ macro_rules! assert_ne { /// assert_matches!(c, Ok(x) | Err(x) if x.len() < 100); /// ``` #[unstable(feature = "assert_matches", issue = "82775")] -#[allow_internal_unstable(core_panic)] +#[allow_internal_unstable(core_panic, panic_internals)] #[rustc_macro_transparency = "semitransparent"] pub macro assert_matches { ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => ({ @@ -173,9 +177,12 @@ pub macro assert_matches { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Match, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($($pattern)|+ $(if $guard)?), + }, left_val, - $crate::stringify!($($pattern)|+ $(if $guard)?), $crate::option::Option::None ); } @@ -186,9 +193,12 @@ pub macro assert_matches { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::panicking::assert_matches_failed( - $crate::stringify!($left), + &$crate::panic::assert_info::BinaryAssertionStaticData { + kind: $crate::panic::assert_info::BinaryAssertKind::Match, + left_expr: $crate::stringify!($left), + right_expr: $crate::stringify!($($pattern)|+ $(if $guard)?), + }, left_val, - $crate::stringify!($($pattern)|+ $(if $guard)?), $crate::option::Option::Some($crate::format_args!($($arg)+)) ); } diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index c301bfad69741..6cacf239c00ab 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -2,9 +2,6 @@ #![stable(feature = "core_panic_info", since = "1.41.0")] -mod location; -mod panic_info; -mod unwind_safe; #[unstable( feature = "panic_internals", reason = "internal details of the implementation of the `panic!` and related macros", @@ -12,13 +9,16 @@ mod unwind_safe; )] #[doc(hidden)] pub mod assert_info; +mod location; #[unstable( feature = "panic_internals", reason = "internal details of the implementation of the `panic!` and related macros", issue = "none" )] #[doc(hidden)] -pub mod extra_info; +pub mod panic_description; +mod panic_info; +mod unwind_safe; use crate::any::Any; @@ -50,10 +50,7 @@ pub macro panic_2015 { $crate::panicking::panic_display(&$arg) ), ($fmt:expr, $($arg:tt)+) => ( - $crate::panicking::panic_fmt( - $crate::const_format_args!($fmt, $($arg)+), - $crate::option::Option::None, - ) + $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) ), } @@ -71,10 +68,7 @@ pub macro panic_2021 { $crate::panicking::panic_display(&$arg) ), ($($t:tt)+) => ( - $crate::panicking::panic_fmt( - $crate::const_format_args!($($t)+), - $crate::option::Option::None, - ) + $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) ), } diff --git a/library/core/src/panic/assert_info.rs b/library/core/src/panic/assert_info.rs index f60d5e7234511..ffd94fba24bbd 100644 --- a/library/core/src/panic/assert_info.rs +++ b/library/core/src/panic/assert_info.rs @@ -1,73 +1,97 @@ -use crate::fmt::Debug; +use crate::fmt::{self, Debug}; /// Information about a failed assertion. #[derive(Debug)] pub struct AssertInfo<'a> { /// The assertion that failed. pub assertion: Assertion<'a>, - /// The name of the macro that triggered the panic. - pub macro_name: &'static str, /// Optional additional message to include in the failure report. pub message: Option>, } +impl fmt::Display for AssertInfo<'_> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.assertion { + Assertion::Binary(ref assertion) => match self.message { + Some(message) => write!( + formatter, + r#"assertion failed: `(left {} right)` + left: `{:?}`, + right: `{:?}`: {}"#, + assertion.static_data.kind.op(), + assertion.left_val, + assertion.right_val, + message + ), + None => write!( + formatter, + r#"assertion failed: `(left {} right)` + left: `{:?}`, + right: `{:?}`"#, + assertion.static_data.kind.op(), + assertion.left_val, + assertion.right_val + ), + }, + } + } +} + /// Details about the expression that failed an assertion. #[derive(Debug)] pub enum Assertion<'a> { - /// The failed assertion is a boolean expression. - /// - /// This variant is only used for expressions that can't be described more specifically - /// by another variant. - Bool(BoolAssertion), - - /// The failed assertion is a binary comparison expression. - /// - /// This is used by `assert_eq!()`, `assert_ne!()` and expressions like - /// `assert!(x > 10)`. + /// The failed assertion is a binary expression. Binary(BinaryAssertion<'a>), } -/// Information about a failed boolean assertion. -/// -/// The expression was asserted to be true, but it evaluated to false. -/// -/// This struct is only used for assertion failures that can't be described more specifically -/// by another assertion type. +/// Information about a failed binary assertion. #[derive(Debug)] -pub struct BoolAssertion { - /// The expression that was evaluated to false. - pub expr: &'static str, +pub struct BinaryAssertion<'a> { + /// Static information about the failed assertion. + pub static_data: &'static BinaryAssertionStaticData, + /// The left value of the binary assertion. + pub left_val: &'a dyn Debug, + /// The right value of the binary assertion. + pub right_val: &'a dyn Debug, } -/// Information about a failed binary comparison assertion. +/// Information about a binary assertion that can be constructed at compile time. /// -/// The left expression was compared with the right expression using `op`, -/// and the comparison evaluted to false. -/// -/// This struct is used for `assert_eq!()`, `assert_ne!()` and expressions like -/// `assert!(x > 10)`. +/// This struct helps to reduce the size `AssertInfo`. #[derive(Debug)] -pub struct BinaryAssertion<'a> { - /// The operator used to compare left and right. - pub op: &'static str, - /// The left expression as string. +pub struct BinaryAssertionStaticData { + /// The kind of the binary assertion + pub kind: BinaryAssertKind, + /// The left expression of the binary assertion. pub left_expr: &'static str, - /// The right expression as string. + /// The right expression of the binary assertion. pub right_expr: &'static str, - /// The value of the left expression. - pub left_val: &'a dyn Debug, - /// The value of the right expression. - pub right_val: &'a dyn Debug, } -impl<'a> From for Assertion<'a> { - fn from(other: BoolAssertion) -> Self { - Self::Bool(other) - } +/// The kind of a binary assertion +#[derive(Debug)] +pub enum BinaryAssertKind { + Eq, + Ne, + Match, } -impl<'a> From> for Assertion<'a> { - fn from(other: BinaryAssertion<'a>) -> Self { - Self::Binary(other) +impl BinaryAssertKind { + /// The name of the macro that triggered the panic. + pub fn macro_name(&self) -> &'static str { + match self { + Self::Eq { .. } => "assert_eq", + Self::Ne { .. } => "assert_ne", + Self::Match { .. } => "assert_matches", + } + } + + /// Symbolic representation of the binary assertion. + pub fn op(&self) -> &'static str { + match self { + Self::Eq { .. } => "==", + Self::Ne { .. } => "!=", + Self::Match { .. } => "matches", + } } } diff --git a/library/core/src/panic/extra_info.rs b/library/core/src/panic/extra_info.rs deleted file mode 100644 index a212aea992a52..0000000000000 --- a/library/core/src/panic/extra_info.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::panic::assert_info::AssertInfo; - -#[derive(Debug, Copy, Clone)] -#[non_exhaustive] -pub enum ExtraInfo<'a> { - AssertInfo(&'a AssertInfo<'a>), -} diff --git a/library/core/src/panic/panic_description.rs b/library/core/src/panic/panic_description.rs new file mode 100644 index 0000000000000..2ece46c38cf94 --- /dev/null +++ b/library/core/src/panic/panic_description.rs @@ -0,0 +1,27 @@ +use crate::fmt; +use crate::panic::assert_info::AssertInfo; + +/// Describes the cause of the panic. +#[doc(hidden)] +#[derive(Debug, Copy, Clone)] +#[non_exhaustive] +pub enum PanicDescription<'a> { + /// Formatted arguments that were passed to the panic. + Message(&'a fmt::Arguments<'a>), + /// Information about the assertion that caused the panic. + AssertInfo(&'a AssertInfo<'a>), +} + +#[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" +)] +impl fmt::Display for PanicDescription<'_> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Message(message) => write!(formatter, "{}", message), + Self::AssertInfo(info) => write!(formatter, "{}", info), + } + } +} diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 22b5b3351da3a..879e460188a76 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -1,7 +1,7 @@ use crate::any::Any; use crate::fmt; use crate::panic::assert_info::AssertInfo; -use crate::panic::extra_info::ExtraInfo; +use crate::panic::panic_description::PanicDescription; use crate::panic::Location; /// A struct providing information about a panic. @@ -31,9 +31,8 @@ use crate::panic::Location; #[derive(Debug)] pub struct PanicInfo<'a> { payload: &'a (dyn Any + Send), - message: Option<&'a fmt::Arguments<'a>>, + description: Option>, location: &'a Location<'a>, - extra_info: Option>, } impl<'a> PanicInfo<'a> { @@ -45,11 +44,11 @@ impl<'a> PanicInfo<'a> { #[doc(hidden)] #[inline] pub fn internal_constructor( - message: Option<&'a fmt::Arguments<'a>>, + description: Option>, location: &'a Location<'a>, ) -> Self { struct NoPayload; - PanicInfo { location, message, payload: &NoPayload, extra_info: None } + PanicInfo { location, description, payload: &NoPayload } } #[unstable( @@ -89,12 +88,27 @@ impl<'a> PanicInfo<'a> { self.payload } + /// Get the description of the cause of the panic. + /// + /// Returns `None` if no description was provided. + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + pub fn description(&self) -> Option> { + self.description + } + /// If the `panic!` macro from the `core` crate (not from `std`) /// was used with a formatting string and some additional arguments, /// returns that message ready to be used for example with [`fmt::write`] #[unstable(feature = "panic_info_message", issue = "66745")] pub fn message(&self) -> Option<&fmt::Arguments<'_>> { - self.message + match self.description { + Some(PanicDescription::Message(message)) => Some(message), + _ => None, + } } /// Returns information about the location from which the panic originated, @@ -128,28 +142,6 @@ impl<'a> PanicInfo<'a> { Some(&self.location) } - #[unstable( - feature = "panic_internals", - reason = "internal details of the implementation of the `panic!` and related macros", - issue = "none" - )] - #[doc(hidden)] - #[inline] - pub fn set_extra_info(&mut self, info: Option>) { - self.extra_info = info; - } - - #[unstable( - feature = "panic_internals", - reason = "internal details of the implementation of the `panic!` and related macros", - issue = "none" - )] - #[doc(hidden)] - #[inline] - pub fn extra_info(&self) -> Option> { - self.extra_info - } - /// Get the information about the assertion that caused the panic. /// /// Returns `None` if the panic was not caused by an assertion. @@ -159,7 +151,10 @@ impl<'a> PanicInfo<'a> { issue = "none" )] pub fn assert_info(&self) -> Option<&AssertInfo<'_>> { - if let Some(ExtraInfo::AssertInfo(x)) = &self.extra_info { Some(x) } else { None } + match self.description { + Some(PanicDescription::AssertInfo(info)) => Some(info), + _ => None, + } } } @@ -167,8 +162,8 @@ impl<'a> PanicInfo<'a> { impl fmt::Display for PanicInfo<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("panicked at ")?; - if let Some(message) = self.message { - write!(formatter, "'{}', ", message)? + if let Some(description) = self.description { + write!(formatter, "'{}', ", description)? } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() { write!(formatter, "'{}', ", payload)? } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 6aef1d1325851..aac9210364817 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -27,8 +27,10 @@ )] use crate::fmt; -use crate::panic::assert_info::{AssertInfo, Assertion, BinaryAssertion}; -use crate::panic::extra_info::ExtraInfo; +use crate::panic::assert_info::{ + AssertInfo, Assertion, BinaryAssertion, BinaryAssertionStaticData, +}; +use crate::panic::panic_description::PanicDescription; use crate::panic::{Location, PanicInfo}; /// The underlying implementation of libcore's `panic!` macro when no formatting is used. @@ -49,14 +51,14 @@ pub fn panic(expr: &'static str) -> ! { // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), None); + panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); } #[inline] #[track_caller] #[lang = "panic_str"] // needed for const-evaluated panics pub fn panic_str(expr: &str) -> ! { - panic_fmt(format_args!("{}", expr), None); + panic_fmt(format_args!("{}", expr)); } #[inline] @@ -84,14 +86,20 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { /// site as much as possible (so that `panic!()` has as low an impact /// on (e.g.) the inlining of other functions as possible), by moving /// the actual formatting into this shared place. +#[inline] +#[track_caller] +#[lang = "panic_fmt"] // needed for const-evaluated panics +pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + panic_description(PanicDescription::Message(&fmt)) +} + #[cold] // If panic_immediate_abort, inline the abort call, // otherwise avoid inlining because of it is cold path. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[lang = "panic_fmt"] // needed for const-evaluated panics -pub fn panic_fmt(fmt: fmt::Arguments<'_>, extra_info: Option>) -> ! { +fn panic_description(description: PanicDescription<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -103,8 +111,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, extra_info: Option>) -> fn panic_impl(pi: &PanicInfo<'_>) -> !; } - let mut pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller()); - pi.set_extra_info(extra_info); + let pi = PanicInfo::internal_constructor(Some(description), Location::caller()); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } @@ -123,31 +130,21 @@ pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { } } -#[derive(Debug)] -#[doc(hidden)] -pub enum AssertKind { - Eq, - Ne, - Match, -} - /// Internal function for `assert_eq!` and `assert_ne!` macros #[cold] #[track_caller] #[doc(hidden)] pub fn assert_failed( - kind: AssertKind, - left_expr: &'static str, + static_data: &'static BinaryAssertionStaticData, left_val: &T, - right_expr: &'static str, right_val: &U, - args: Option>, + message: Option>, ) -> ! where T: fmt::Debug + ?Sized, U: fmt::Debug + ?Sized, { - assert_failed_inner(kind, left_expr, &left_val, right_expr, &right_val, args) + assert_failed_inner(static_data, &left_val, &right_val, message) } /// Internal function for `assert_match!` @@ -155,10 +152,9 @@ where #[track_caller] #[doc(hidden)] pub fn assert_matches_failed( - left_expr: &'static str, + static_data: &'static BinaryAssertionStaticData, left_val: &T, - right_pattern: &'static str, - args: Option>, + message: Option>, ) -> ! { // Use the Display implementation to display the pattern. struct Pattern<'a>(&'a str); @@ -167,70 +163,19 @@ pub fn assert_matches_failed( fmt::Display::fmt(self.0, f) } } - assert_failed_inner( - AssertKind::Match, - left_expr, - &left_val, - right_pattern, - &Pattern(right_pattern), - args, - ); + assert_failed_inner(static_data, &left_val, &Pattern(static_data.right_expr), message) } /// Non-generic version of the above functions, to avoid code bloat. #[track_caller] fn assert_failed_inner( - kind: AssertKind, - left_expr: &'static str, + static_data: &'static BinaryAssertionStaticData, left_val: &dyn fmt::Debug, - right_expr: &'static str, right_val: &dyn fmt::Debug, - args: Option>, + message: Option>, ) -> ! { - let (op, macro_name) = match kind { - AssertKind::Eq => ("==", "assert_eq"), - AssertKind::Ne => ("!=", "assert_ne"), - AssertKind::Match => ("matches", "assert_matches"), - }; - - match args { - Some(args) => panic_fmt( - format_args!( - r#"assertion failed: `(left {} right)` - left: `{:?}`, - right: `{:?}`: {}"#, - op, left_val, right_val, args - ), - Some(ExtraInfo::AssertInfo(&AssertInfo { - assertion: Assertion::Binary(BinaryAssertion { - op, - left_expr, - right_expr, - left_val, - right_val, - }), - macro_name, - message: Some(args), - })), - ), - None => panic_fmt( - format_args!( - r#"assertion failed: `(left {} right)` - left: `{:?}`, - right: `{:?}`"#, - op, left_val, right_val - ), - Some(ExtraInfo::AssertInfo(&AssertInfo { - assertion: Assertion::Binary(BinaryAssertion { - op, - left_expr, - right_expr, - left_val, - right_val, - }), - macro_name, - message: None, - })), - ), - } + panic_description(PanicDescription::AssertInfo(&AssertInfo { + assertion: Assertion::Binary(BinaryAssertion { static_data, left_val, right_val }), + message, + })) } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 3243f8a3aa7b3..161c434b901f2 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -9,11 +9,10 @@ #![deny(unsafe_op_in_unsafe_fn)] -use core::panic::extra_info::ExtraInfo; +use core::panic::panic_description::PanicDescription; use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; -use crate::fmt; use crate::intrinsics; use crate::mem::{self, ManuallyDrop}; use crate::process; @@ -443,12 +442,12 @@ pub fn panicking() -> bool { #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { - inner: &'a fmt::Arguments<'a>, + inner: &'a PanicDescription<'a>, string: Option, } impl<'a> PanicPayload<'a> { - fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { + fn new(inner: &'a PanicDescription<'a>) -> PanicPayload<'a> { PanicPayload { inner, string: None } } @@ -459,7 +458,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); - drop(s.write_fmt(*inner)); + drop(write!(s, "{}", *inner)); s }) } @@ -492,18 +491,18 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { } let loc = info.location().unwrap(); // The current implementation always returns Some - let msg = info.message().unwrap(); // The current implementation always returns Some + let descr = info.description().unwrap(); // The current implementation always returns Some crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - if let Some(msg) = msg.as_str() { - rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.extra_info()); + let descr_str = match descr { + PanicDescription::Message(message) => message.as_str(), + _ => None, + }; + + if let Some(descr_str) = descr_str { + rust_panic_with_hook(&mut StrPanicPayload(descr_str), info.description(), loc); } else { - rust_panic_with_hook( - &mut PanicPayload::new(msg), - info.message(), - loc, - info.extra_info(), - ); + rust_panic_with_hook(&mut PanicPayload::new(&descr), info.description(), loc); } }) } @@ -526,7 +525,7 @@ pub fn begin_panic(msg: M) -> ! { let loc = Location::caller(); return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, None) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc) }); struct PanicPayload { @@ -569,9 +568,8 @@ pub fn begin_panic(msg: M) -> ! { /// abort or unwind. fn rust_panic_with_hook( payload: &mut dyn BoxMeUp, - message: Option<&fmt::Arguments<'_>>, + description: Option>, location: &Location<'_>, - extra_info: Option>, ) -> ! { let (must_abort, panics) = panic_count::increase(); @@ -588,14 +586,14 @@ fn rust_panic_with_hook( } else { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must to avoid here. - let panicinfo = PanicInfo::internal_constructor(message, location); + let panicinfo = PanicInfo::internal_constructor(description, location); rtprintpanic!("{}\npanicked after panic::always_abort(), aborting.\n", panicinfo); } intrinsics::abort() } unsafe { - let mut info = PanicInfo::internal_constructor(message, location); + let mut info = PanicInfo::internal_constructor(description, location); let _guard = HOOK_LOCK.read(); match HOOK { // Some platforms (like wasm) know that printing to stderr won't ever actually @@ -607,12 +605,10 @@ fn rust_panic_with_hook( Hook::Default if panic_output().is_none() => {} Hook::Default => { info.set_payload(payload.get()); - info.set_extra_info(extra_info); default_hook(&info); } Hook::Custom(ptr) => { info.set_payload(payload.get()); - info.set_extra_info(extra_info); (*ptr)(&info); } }; diff --git a/library/test/src/pretty_print_assertion.rs b/library/test/src/pretty_print_assertion.rs index ea446b1dcc375..7e784c94912ab 100644 --- a/library/test/src/pretty_print_assertion.rs +++ b/library/test/src/pretty_print_assertion.rs @@ -1,9 +1,8 @@ -use core::panic::assert_info::{AssertInfo, Assertion, BinaryAssertion, BoolAssertion}; +use core::panic::assert_info::{AssertInfo, Assertion, BinaryAssertion}; use core::panic::Location; const RED: &str = "\x1b[31m"; const YELLOW: &str = "\x1b[33m"; -const BLUE: &str = "\x1b[34m"; const MAGENTA: &str = "\x1b[35m"; const CYAN: &str = "\x1b[36m"; const BOLD: &str = "\x1b[1m"; @@ -14,22 +13,19 @@ const RESET: &str = "\x1b[0m"; /// If `ansi_colors` is true, this function unconditionally prints ANSI color codes. /// It should only be set to true only if it is known that the terminal supports it. pub fn pretty_print_assertion(assert: &AssertInfo<'_>, loc: Location<'_>, ansi_colors: bool) { - let macro_name = assert.macro_name; if ansi_colors { print_pretty_header(loc); - match &assert.assertion { - Assertion::Bool(assert) => print_pretty_bool_assertion(macro_name, assert), - Assertion::Binary(assert) => print_pretty_binary_assertion(macro_name, assert), - } + match assert.assertion { + Assertion::Binary(ref assertion) => print_pretty_binary_assertion(assertion), + }; if let Some(msg) = &assert.message { print_pretty_message(msg); } } else { print_plain_header(loc); - match &assert.assertion { - Assertion::Bool(assert) => print_plain_bool_assertion(macro_name, assert), - Assertion::Binary(assert) => print_plain_binary_assertion(macro_name, assert), - } + match assert.assertion { + Assertion::Binary(ref assertion) => print_plain_binary_assertion(assertion), + }; if let Some(msg) = &assert.message { print_plain_message(msg); } @@ -52,113 +48,43 @@ fn print_pretty_header(loc: Location<'_>) { ); } -fn print_plain_bool_assertion(macro_name: &'static str, assert: &BoolAssertion) { +fn print_plain_binary_assertion(assertion: &BinaryAssertion<'_>) { eprint!( concat!( "Assertion:\n", - " {macro_name}!( {expr} )\n", + " {macro_name}!( {left_expr}, {right_expr} )\n", "Expansion:\n", - " {macro_name}!( false )\n", + " {macro_name}!( {left_val:?}, {right_val:?} )\n", ), - macro_name = macro_name, - expr = assert.expr, - ) + macro_name = assertion.static_data.kind.macro_name(), + left_expr = assertion.static_data.left_expr, + right_expr = assertion.static_data.right_expr, + left_val = assertion.left_val, + right_val = assertion.right_val, + ); } -fn print_pretty_bool_assertion(macro_name: &'static str, assert: &BoolAssertion) { +fn print_pretty_binary_assertion(assertion: &BinaryAssertion<'_>) { eprint!( concat!( "{bold}Assertion:{reset}\n", - " {magenta}{macro_name}!( {cyan}{expr} {magenta}){reset}\n", + " {magenta}{macro_name}!( {cyan}{left_expr}{magenta}, {yellow}{right_expr} {magenta}){reset}\n", "{bold}Expansion:{reset}\n", - " {magenta}{macro_name}!( {cyan}false {magenta}){reset}\n", + " {magenta}{macro_name}!( {cyan}{left_val:?}{magenta}, {yellow}{right_val:?} {magenta}){reset}\n", ), - magenta = MAGENTA, cyan = CYAN, - reset = RESET, + magenta = MAGENTA, + yellow = YELLOW, bold = BOLD, - macro_name = macro_name, - expr = assert.expr, + reset = RESET, + macro_name = assertion.static_data.kind.macro_name(), + left_expr = assertion.static_data.left_expr, + right_expr = assertion.static_data.right_expr, + left_val = assertion.left_val, + right_val = assertion.right_val, ); } -fn print_plain_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { - if is_specalized_macro(macro_name) { - eprint!( - concat!( - "Assertion:\n", - " {macro_name}!( {left_expr}, {right_expr} )\n", - "Expansion:\n", - " {macro_name}!( {left_val:?}, {right_val:?} )\n", - ), - macro_name = macro_name, - left_expr = assert.left_expr, - right_expr = assert.right_expr, - left_val = assert.left_val, - right_val = assert.right_val, - ); - } else { - eprint!( - concat!( - "Assertion:\n", - " {macro_name}!( {left_expr} {op} {right_expr} )\n", - "Expansion:\n", - " {macro_name}!( {left_val:?} {op} {right_val:?} )\n", - ), - macro_name = macro_name, - op = assert.op, - left_expr = assert.left_expr, - right_expr = assert.right_expr, - left_val = assert.left_val, - right_val = assert.right_val, - ); - }; -} - -fn print_pretty_binary_assertion(macro_name: &'static str, assert: &BinaryAssertion<'_>) { - if is_specalized_macro(macro_name) { - eprint!( - concat!( - "{bold}Assertion:{reset}\n", - " {magenta}{macro_name}!( {cyan}{left_expr}{magenta}, {yellow}{right_expr} {magenta}){reset}\n", - "{bold}Expansion:{reset}\n", - " {magenta}{macro_name}!( {cyan}{left_val:?}{magenta}, {yellow}{right_val:?} {magenta}){reset}\n", - ), - cyan = CYAN, - magenta = MAGENTA, - yellow = YELLOW, - bold = BOLD, - reset = RESET, - macro_name = macro_name, - left_expr = assert.left_expr, - right_expr = assert.right_expr, - left_val = assert.left_val, - right_val = assert.right_val, - ); - } else { - eprint!( - concat!( - "{bold}Assertion:{reset}\n", - " {magenta}{macro_name}!( {cyan}{left_expr} {bold}{blue}{op}{reset} {yellow}{right_expr} {magenta}){reset}\n", - "{bold}Expansion:{reset}\n", - " {magenta}{macro_name}!( {cyan}{left_val:?} {bold}{blue}{op}{reset} {yellow}{right_val:?} {magenta}){reset}\n", - ), - blue = BLUE, - cyan = CYAN, - magenta = MAGENTA, - yellow = YELLOW, - bold = BOLD, - reset = RESET, - macro_name = macro_name, - op = assert.op, - left_expr = assert.left_expr, - right_expr = assert.right_expr, - left_val = assert.left_val, - right_val = assert.right_val, - ); - }; -} - fn print_plain_message(message: &std::fmt::Arguments<'_>) { eprintln!("Message:\n {}", message); } @@ -166,9 +92,3 @@ fn print_plain_message(message: &std::fmt::Arguments<'_>) { fn print_pretty_message(message: &std::fmt::Arguments<'_>) { eprintln!("{bold}Message:{reset}\n {msg}", bold = BOLD, reset = RESET, msg = message,); } - -fn is_specalized_macro(macro_name: &str) -> bool { - // Specialized macros already imply the operator in their name, - // so we print them without repeating the operator. - macro_name == "assert_eq" || macro_name == "assert_neq" || macro_name == "assert_matches" -} From ec39e42ecb0d0be5af694a95c412f3e18f5f593c Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Mon, 16 Aug 2021 23:52:27 +0200 Subject: [PATCH 10/11] Unify signatures of `GetConsoleMode` by changing `HANDLE` to `c_void` `GetConsoleMode` was declared twice with different signatures. The signatures have contained different definitions of `HANDLE`. --- library/test/src/helpers/isatty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/test/src/helpers/isatty.rs b/library/test/src/helpers/isatty.rs index 874ecc3764572..f770a20a8eefa 100644 --- a/library/test/src/helpers/isatty.rs +++ b/library/test/src/helpers/isatty.rs @@ -10,7 +10,7 @@ cfg_if::cfg_if! { pub fn stdout_isatty() -> bool { type DWORD = u32; type BOOL = i32; - type HANDLE = *mut u8; + type HANDLE = *mut core::ffi::c_void; type LPDWORD = *mut u32; const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; extern "system" { From e0279b3456e0b57298cf8c569b10fcf64550733c Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Tue, 18 May 2021 00:13:12 +0200 Subject: [PATCH 11/11] Bless test output --- .../issue_73223.main.PreCodegen.32bit.diff | 64 ++++++++------- .../issue_73223.main.PreCodegen.64bit.diff | 64 ++++++++------- ..._73223.main.SimplifyArmIdentity.32bit.diff | 73 ++++++++--------- ..._73223.main.SimplifyArmIdentity.64bit.diff | 73 ++++++++--------- ...asts.SimplifyCfg-elaborate-drops.after.mir | 80 +++++++++++-------- .../defaults-cyclic-fail.stderr | 2 +- 6 files changed, 180 insertions(+), 176 deletions(-) diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index 95632293d9991..ff9d6a6a6d0a6 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -13,11 +13,13 @@ let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _14: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _15: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _19: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _20: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -25,14 +27,11 @@ debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _22: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _14; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } + let mut _21: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -60,14 +59,14 @@ StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _22 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[1])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } - _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) } + _8 = _22; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -89,27 +88,30 @@ bb1: { StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = const main::promoted[0]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: &core::panic::assert_info::BinaryAssertionStaticData + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: &core::panic::assert_info::BinaryAssertionStaticData, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } + _15 = _21; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _14 = _15; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = _9; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = _17; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_19); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _19 = _10; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = _19; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(move _14, move _16, move _18, move _20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'static core::panic::assert_info::BinaryAssertionStaticData, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index 95632293d9991..ff9d6a6a6d0a6 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -13,11 +13,13 @@ let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _14: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _15: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _19: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _20: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -25,14 +27,11 @@ debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _22: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _14; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } + let mut _21: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -60,14 +59,14 @@ StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _22 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[1])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } - _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) } + _8 = _22; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -89,27 +88,30 @@ bb1: { StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = const main::promoted[0]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: &core::panic::assert_info::BinaryAssertionStaticData + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: &core::panic::assert_info::BinaryAssertionStaticData, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } + _15 = _21; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _14 = _15; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = _9; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = _17; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_19); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _19 = _10; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = _19; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(move _14, move _16, move _18, move _20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'static core::panic::assert_info::BinaryAssertionStaticData, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index 946aab9c6e898..8abfbc6d307ef 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -19,13 +19,16 @@ let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _20: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _21: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _22: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _23: core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _24: core::panic::assert_info::BinaryAssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _27: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _27: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _28: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _29: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -33,14 +36,11 @@ debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _31: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _20: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _20; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } + let mut _30: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -81,14 +81,14 @@ StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _31 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[1])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } - _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) } + _11 = _31; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -113,36 +113,31 @@ bb3: { StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_21); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_22); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _30 = const main::promoted[0]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + ty: &core::panic::assert_info::BinaryAssertionStaticData + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: &core::panic::assert_info::BinaryAssertionStaticData, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } + _22 = _30; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = _22; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_25); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_26); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _26 = _13; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _25 = _26; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_27); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_28); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _28 = _14; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _27 = _28; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_29); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_29) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(move _21, move _25, move _27, move _29); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'static core::panic::assert_info::BinaryAssertionStaticData, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb4: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 946aab9c6e898..8abfbc6d307ef 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -19,13 +19,16 @@ let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _20: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _21: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _22: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _23: core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _24: core::panic::assert_info::BinaryAssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _27: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _27: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _28: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _29: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -33,14 +36,11 @@ debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _31: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _20: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _20; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } + let mut _30: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -81,14 +81,14 @@ StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _31 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[1])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } - _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) } + _11 = _31; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -113,36 +113,31 @@ bb3: { StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_21); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_22); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _30 = const main::promoted[0]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + ty: &core::panic::assert_info::BinaryAssertionStaticData + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: &core::panic::assert_info::BinaryAssertionStaticData, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } + _22 = _30; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = _22; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_25); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_26); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _26 = _13; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _25 = _26; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_27); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_28); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _28 = _14; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _27 = _28; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_29); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_29) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(move _21, move _25, move _27, move _29); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'static core::panic::assert_info::BinaryAssertionStaticData, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb4: { diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index ee99d033af320..146955b134754 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -23,13 +23,16 @@ fn array_casts() -> () { let mut _24: usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _26: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _28: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _29: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _30: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _31: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _27: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _28: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _29: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _30: core::panic::assert_info::BinaryAssertionStaticData; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _31: core::panic::assert_info::BinaryAssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _32: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _33: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _34: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _34: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _35: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _36: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug x => _1; // in scope 1 at $DIR/retag.rs:58:9: 58:14 let _2: *mut usize; // in scope 1 at $DIR/retag.rs:59:9: 59:10 @@ -45,16 +48,13 @@ fn array_casts() -> () { debug p => _9; // in scope 5 at $DIR/retag.rs:63:9: 63:10 let _20: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _21: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _35: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _38: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 6 { } scope 7 { debug left_val => _20; // in scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _21; // in scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _27: core::panicking::AssertKind; // in scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 8 { - debug kind => _27; // in scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } + let mut _37: &core::panic::assert_info::BinaryAssertionStaticData; // in scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -121,15 +121,15 @@ fn array_casts() -> () { _14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _35 = const array_casts::promoted[0]; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _38 = const array_casts::promoted[1]; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &usize - // + val: Unevaluated(array_casts, [], Some(promoted[0])) + // + val: Unevaluated(array_casts, [], Some(promoted[1])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } - Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) } + Retag(_38); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = &(*_38); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -156,28 +156,38 @@ fn array_casts() -> () { bb3: { StorageLive(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _34 = Option::::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_28); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_29); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _37 = const array_casts::promoted[0]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: &core::panic::assert_info::BinaryAssertionStaticData + // + val: Unevaluated(array_casts, [], Some(promoted[0])) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &core::panic::assert_info::BinaryAssertionStaticData, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } + Retag(_37); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _29 = &(*_37); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_29); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _28 = &(*_29); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_28); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_32); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_33); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _33 = &(*_20); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_33); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _32 = &(*_33); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_32); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_34); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_35); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _35 = &(*_21); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_35); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _34 = &(*_35); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_34); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_36); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _36 = Option::::None; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(move _28, move _32, move _34, move _36); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'static core::panic::assert_info::BinaryAssertionStaticData, &'r usize, &'s usize, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb4: { diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 3fb4ab72fe6d6..616ac9053fd53 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -32,7 +32,7 @@ note: ...which requires const-evaluating + checking `Tr::B`... LL | const B: u8 = Self::A; | ^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle -note: cycle used when const-evaluating + checking `main::promoted[1]` +note: cycle used when const-evaluating + checking `main::promoted[2]` --> $DIR/defaults-cyclic-fail.rs:14:1 | LL | fn main() {