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.
This commit is contained in:
commit
b60f7b51a2
105 changed files with 488 additions and 304 deletions
|
@ -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::*;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
|
||||
|
|
|
@ -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 { .. } |
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue