diff options
| author | bors <bors@rust-lang.org> | 2023-08-25 08:47:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-08-25 08:47:18 +0000 |
| commit | b60f7b51a27dfd9cbc5ecaa56ee679cd1b67f4c4 (patch) | |
| tree | 28ce7533ebaf2f1823cc1e070e34df397f43f04d /compiler/rustc_middle | |
| parent | 4535d33e337104e7961ca7f2086627cbb07919dd (diff) | |
| parent | df5a248cb1d557f8df9c9d0660e8d704bc1e0919 (diff) | |
| download | rust-b60f7b51a27dfd9cbc5ecaa56ee679cd1b67f4c4.tar.gz rust-b60f7b51a27dfd9cbc5ecaa56ee679cd1b67f4c4.zip | |
Auto merge of #115045 - RalfJung:unwind-terminate-reason, r=davidtwco
when terminating during unwinding, show the reason why
With this, the output on double-panic becomes something like that:
```
thread 'main' panicked at src/tools/miri/tests/fail/panic/double_panic.rs:15:5:
first
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at src/tools/miri/tests/fail/panic/double_panic.rs:10:9:
second
stack backtrace:
0: 0xbe273a - std::backtrace_rs::backtrace::miri::trace_unsynchronized::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:99:5
1: 0xbe22e6 - std::backtrace_rs::backtrace::miri::trace::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:62:14
2: 0xbe1086 - std::backtrace_rs::backtrace::trace_unsynchronized::<[closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
3: 0xba3afd - std::sys_common::backtrace::_print_fmt
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:67:5
4: 0xba2471 - <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:44:22
5: 0xbcf754 - core::fmt::rt::Argument::<'_>::fmt
at /home/r/src/rust/rustc.3/library/core/src/fmt/rt.rs:138:9
6: 0x9b8f81 - std::fmt::write
at /home/r/src/rust/rustc.3/library/core/src/fmt/mod.rs:1094:17
7: 0x21391d - <std::sys::unix::stdio::Stderr as std::io::Write>::write_fmt
at /home/r/src/rust/rustc.3/library/std/src/io/mod.rs:1714:15
8: 0xba37b1 - std::sys_common::backtrace::_print
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:47:5
9: 0xba365b - std::sys_common::backtrace::print
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:34:9
10: 0x143c67 - std::panic_hook_with_disk_dump::{closure#1}
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:278:22
11: 0x144187 - std::panic_hook_with_disk_dump
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:312:9
12: 0x143659 - std::panicking::default_hook
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:239:5
13: 0x1482a7 - std::panicking::rust_panic_with_hook
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:729:13
14: 0x1475d5 - std::rt::begin_panic::<&str>::{closure#0}
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:650:9
15: 0xba496a - std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:170:18
16: 0x147599 - std::rt::begin_panic::<&str>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:649:12
17: 0x31916 - <Foo as std::ops::Drop>::drop
at src/tools/miri/tests/fail/panic/double_panic.rs:10:9
18: 0x1a2b5e - std::ptr::drop_in_place::<Foo> - shim(Some(Foo))
at /home/r/src/rust/rustc.3/library/core/src/ptr/mod.rs:497:1
19: 0x202bf - main
at src/tools/miri/tests/fail/panic/double_panic.rs:16:1
20: 0xcc6a8 - <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:250:5
21: 0xba47d9 - std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:154:18
22: 0x141a6a - std::rt::lang_start::<()>::{closure#0}
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:166:18
23: 0xcca18 - std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once
at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:284:13
24: 0x146469 - std::panicking::try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
25: 0x145e09 - std::panicking::try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
26: 0x7b0ac - std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
27: 0x14189b - std::rt::lang_start_internal::{closure#2}
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:48
28: 0x146481 - std::panicking::try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
29: 0x145e2c - std::panicking::try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
30: 0x7b0d5 - std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
31: 0x1418b0 - std::rt::lang_start_internal
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:20
32: 0x141a97 - std::rt::lang_start::<()>
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:165:17
thread 'main' panicked at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:126:5:
panic in a destructor during cleanup
stack backtrace:
0: 0xe9f6d7 - std::backtrace_rs::backtrace::miri::trace_unsynchronized::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:99:5
1: 0xe9f27d - std::backtrace_rs::backtrace::miri::trace::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:62:14
2: 0xe9e016 - std::backtrace_rs::backtrace::trace_unsynchronized::<[closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
3: 0xba3afd - std::sys_common::backtrace::_print_fmt
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:67:5
4: 0xba2471 - <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:44:22
5: 0xbcf754 - core::fmt::rt::Argument::<'_>::fmt
at /home/r/src/rust/rustc.3/library/core/src/fmt/rt.rs:138:9
6: 0x9b8f81 - std::fmt::write
at /home/r/src/rust/rustc.3/library/core/src/fmt/mod.rs:1094:17
7: 0x4d0895 - <std::sys::unix::stdio::Stderr as std::io::Write>::write_fmt
at /home/r/src/rust/rustc.3/library/std/src/io/mod.rs:1714:15
8: 0xba37b1 - std::sys_common::backtrace::_print
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:47:5
9: 0xba365b - std::sys_common::backtrace::print
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:34:9
10: 0x400bd4 - std::panic_hook_with_disk_dump::{closure#1}
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:278:22
11: 0x144187 - std::panic_hook_with_disk_dump
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:312:9
12: 0x143659 - std::panicking::default_hook
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:239:5
13: 0x1482a7 - std::panicking::rust_panic_with_hook
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:729:13
14: 0x40403b - std::panicking::begin_panic_handler::{closure#0}
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:619:13
15: 0xe618b3 - std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:170:18
16: 0x403fc8 - std::panicking::begin_panic_handler
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:617:5
17: 0xee23e9 - core::panicking::panic_nounwind_fmt
at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:96:14
18: 0xee29e6 - core::panicking::panic_nounwind
at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:126:5
19: 0xee365e - core::panicking::panic_in_cleanup
at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:206:5
20: 0x2028a - main
at src/tools/miri/tests/fail/panic/double_panic.rs:13:1
21: 0x3895ee - <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:250:5
22: 0xe61725 - std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:154:18
23: 0x3fe9aa - std::rt::lang_start::<()>::{closure#0}
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:166:18
24: 0x389962 - std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once
at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:284:13
25: 0x4033b9 - std::panicking::try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
26: 0x402d58 - std::panicking::try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
27: 0x337ff7 - std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
28: 0x3fe7e7 - std::rt::lang_start_internal::{closure#2}
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:48
29: 0x4033d6 - std::panicking::try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
30: 0x402d7f - std::panicking::try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>
at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
31: 0x338028 - std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
32: 0x1418b0 - std::rt::lang_start_internal
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:20
33: 0x3fe9dc - std::rt::lang_start::<()>
at /home/r/src/rust/rustc.3/library/std/src/rt.rs:165:17
thread caused non-unwinding panic. aborting.
```
If we also land https://github.com/rust-lang/rust/pull/115020, the 2nd backtrace disappears, hopefully making the "panic in a destructor during cleanup" easier to see.
Fixes https://github.com/rust-lang/rust/issues/114954.
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/patch.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/terminator.rs | 97 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 2 |
5 files changed, 119 insertions, 41 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9ef3a1b30e4..6484c30167c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1275,9 +1275,11 @@ impl<O> AssertKind<O> { matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..)) } - /// Getting a description does not require `O` to be printable, and does not - /// require allocation. - /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately. + /// Get the message that is printed at runtime when this assertion fails. + /// + /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by + /// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference) + /// instead of printing a static message. pub fn description(&self) -> &'static str { use AssertKind::*; match self { @@ -1303,6 +1305,11 @@ impl<O> AssertKind<O> { } /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing. + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result where O: Debug, @@ -1358,6 +1365,12 @@ impl<O> AssertKind<O> { } } + /// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval). + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn diagnostic_message(&self) -> DiagnosticMessage { use crate::fluent_generated::*; use AssertKind::*; diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index cd74a403ff6..da486c3465a 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -14,7 +14,8 @@ pub struct MirPatch<'tcx> { resume_block: Option<BasicBlock>, // Only for unreachable in cleanup path. unreachable_cleanup_block: Option<BasicBlock>, - terminate_block: Option<BasicBlock>, + // Cached block for UnwindTerminate (with reason) + terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, next_local: usize, } @@ -35,13 +36,15 @@ impl<'tcx> MirPatch<'tcx> { for (bb, block) in body.basic_blocks.iter_enumerated() { // Check if we already have a resume block - if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() { + if matches!(block.terminator().kind, TerminatorKind::UnwindResume) + && block.statements.is_empty() + { result.resume_block = Some(bb); continue; } // Check if we already have an unreachable block - if let TerminatorKind::Unreachable = block.terminator().kind + if matches!(block.terminator().kind, TerminatorKind::Unreachable) && block.statements.is_empty() && block.is_cleanup { @@ -50,8 +53,10 @@ impl<'tcx> MirPatch<'tcx> { } // Check if we already have a terminate block - if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() { - result.terminate_block = Some(bb); + if let TerminatorKind::UnwindTerminate(reason) = block.terminator().kind + && block.statements.is_empty() + { + result.terminate_block = Some((bb, reason)); continue; } } @@ -93,20 +98,20 @@ impl<'tcx> MirPatch<'tcx> { bb } - pub fn terminate_block(&mut self) -> BasicBlock { - if let Some(bb) = self.terminate_block { - return bb; + pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { + if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason { + return cached_bb; } let bb = self.new_block(BasicBlockData { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo::outermost(self.body_span), - kind: TerminatorKind::UnwindTerminate, + kind: TerminatorKind::UnwindTerminate(reason), }), is_cleanup: true, }); - self.terminate_block = Some(bb); + self.terminate_block = Some((bb, reason)); bb } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e91e822f915..79b64a491f4 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -621,7 +621,7 @@ pub enum TerminatorKind<'tcx> { /// /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in /// cleanup blocks. - UnwindTerminate, + UnwindTerminate(UnwindTerminateReason), /// Returns from the function. /// @@ -813,7 +813,7 @@ impl TerminatorKind<'_> { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::UnwindResume => "UnwindResume", - TerminatorKind::UnwindTerminate => "UnwindTerminate", + TerminatorKind::UnwindTerminate(_) => "UnwindTerminate", TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", @@ -842,11 +842,22 @@ pub enum UnwindAction { /// Terminates the execution if unwind happens. /// /// Depending on the platform and situation this may cause a non-unwindable panic or abort. - Terminate, + Terminate(UnwindTerminateReason), /// Cleanups to be done. Cleanup(BasicBlock), } +/// The reason we are terminating the process during unwinding. +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + /// Information about an assertion failure. #[derive(Clone, Hash, HashStable, PartialEq, Debug)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index bd87563e2bb..7eddf13b3fb 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,3 +1,4 @@ +use rustc_hir::LangItem; use smallvec::SmallVec; use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction}; @@ -100,6 +101,40 @@ impl<'a> Iterator for SwitchTargetsIter<'a> { impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {} +impl UnwindAction { + fn cleanup_block(self) -> Option<BasicBlock> { + match self { + UnwindAction::Cleanup(bb) => Some(bb), + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => None, + } + } +} + +impl UnwindTerminateReason { + pub fn as_str(self) -> &'static str { + // Keep this in sync with the messages in `core/src/panicking.rs`. + match self { + UnwindTerminateReason::Abi => "panic in a function that cannot unwind", + UnwindTerminateReason::InCleanup => "panic in a destructor during cleanup", + } + } + + /// A short representation of this used for MIR printing. + pub fn as_short_str(self) -> &'static str { + match self { + UnwindTerminateReason::Abi => "abi", + UnwindTerminateReason::InCleanup => "cleanup", + } + } + + pub fn lang_item(self) -> LangItem { + match self { + UnwindTerminateReason::Abi => LangItem::PanicCannotUnwind, + UnwindTerminateReason::InCleanup => LangItem::PanicInCleanup, + } + } +} + #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Terminator<'tcx> { pub source_info: SourceInfo, @@ -156,7 +191,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain((&[]).into_iter().copied()) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -198,7 +233,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain(&mut []) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -215,7 +250,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -234,7 +269,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -271,18 +306,28 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let labels = self.fmt_successor_labels(); assert_eq!(successor_count, labels.len()); - let unwind = match self.unwind() { - // Not needed or included in successors - None | Some(UnwindAction::Cleanup(_)) => None, - Some(UnwindAction::Continue) => Some("unwind continue"), - Some(UnwindAction::Unreachable) => Some("unwind unreachable"), - Some(UnwindAction::Terminate) => Some("unwind terminate"), + // `Cleanup` is already included in successors + let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_))); + let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result { + write!(fmt, "unwind ")?; + match self.unwind() { + // Not needed or included in successors + None | Some(UnwindAction::Cleanup(_)) => unreachable!(), + Some(UnwindAction::Continue) => write!(fmt, "continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"), + Some(UnwindAction::Terminate(reason)) => { + write!(fmt, "terminate({})", reason.as_short_str()) + } + } }; - match (successor_count, unwind) { - (0, None) => Ok(()), - (0, Some(unwind)) => write!(fmt, " -> {unwind}"), - (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), + match (successor_count, show_unwind) { + (0, false) => Ok(()), + (0, true) => { + write!(fmt, " -> ")?; + fmt_unwind(fmt) + } + (1, false) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; for (i, target) in self.successors().enumerate() { @@ -291,8 +336,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } write!(fmt, "{}: {:?}", labels[i], target)?; } - if let Some(unwind) = unwind { - write!(fmt, ", {unwind}")?; + if show_unwind { + write!(fmt, ", ")?; + fmt_unwind(fmt)?; } write!(fmt, "]") } @@ -312,7 +358,9 @@ impl<'tcx> TerminatorKind<'tcx> { Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), UnwindResume => write!(fmt, "resume"), - UnwindTerminate => write!(fmt, "abort"), + UnwindTerminate(reason) => { + write!(fmt, "abort({})", reason.as_short_str()) + } Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({place:?})"), @@ -391,7 +439,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { use self::TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![], + Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], SwitchInt { ref targets, .. } => targets .values @@ -443,7 +491,8 @@ pub enum TerminatorEdges<'mir, 'tcx> { /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { return_: Option<BasicBlock>, - unwind: UnwindAction, + /// The cleanup block, if it exists. + cleanup: Option<BasicBlock>, place: CallReturnPlaces<'mir, 'tcx>, }, /// Special edge for `SwitchInt`. @@ -486,7 +535,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> { use TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => { + Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => { TerminatorEdges::None } @@ -496,7 +545,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Drop { target, unwind, place: _, replace: _ } | FalseUnwind { real_target: target, unwind } => match unwind { UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind), - UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => { + UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => { TerminatorEdges::Single(target) } }, @@ -508,7 +557,7 @@ impl<'tcx> TerminatorKind<'tcx> { Yield { resume: target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { return_: Some(target), - unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup), + cleanup: drop, place: CallReturnPlaces::Yield(resume_arg), } } @@ -516,7 +565,7 @@ impl<'tcx> TerminatorKind<'tcx> { Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { TerminatorEdges::AssignOnReturn { return_: target, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::Call(destination), } } @@ -530,7 +579,7 @@ impl<'tcx> TerminatorKind<'tcx> { unwind, } => TerminatorEdges::AssignOnReturn { return_: destination, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b3d3366ae10..87b04aabe6a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -470,7 +470,7 @@ macro_rules! make_mir_visitor { match kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume | - TerminatorKind::UnwindTerminate | + TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | |
