when terminating during unwinding, show the reason why

This commit is contained in:
Ralf Jung 2023-08-21 09:57:10 +02:00
parent 0b31792ef1
commit 4c53783f3c
88 changed files with 380 additions and 278 deletions

View File

@ -202,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
}
TerminatorKind::Goto { target: _ }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {

View File

@ -770,7 +770,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
}
TerminatorKind::Goto { target: _ }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::UnwindResume
| TerminatorKind::Return
@ -817,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
}
}
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }

View File

@ -1334,7 +1334,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match &term.kind {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable
@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, block_data, "resume on non-cleanup block!")
}
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
if !is_cleanup {
span_mirbug!(self, block_data, "abort on non-cleanup block!")
}
@ -1697,7 +1697,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, ctxt, "unwind on cleanup block")
}
}
UnwindAction::Unreachable | UnwindAction::Terminate => (),
UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
}
}

View File

@ -474,8 +474,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
*destination,
);
}
TerminatorKind::UnwindTerminate => {
codegen_panic_cannot_unwind(fx, source_info);
TerminatorKind::UnwindTerminate(reason) => {
codegen_unwind_terminate(fx, source_info, *reason);
}
TerminatorKind::UnwindResume => {
// FIXME implement unwinding
@ -971,13 +971,14 @@ pub(crate) fn codegen_panic_nounwind<'tcx>(
codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span);
}
pub(crate) fn codegen_panic_cannot_unwind<'tcx>(
pub(crate) fn codegen_unwind_terminate<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
source_info: mir::SourceInfo,
reason: UnwindTerminateReason,
) {
let args = [];
codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span);
codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span);
}
fn codegen_panic_inner<'tcx>(

View File

@ -551,7 +551,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -285,7 +285,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
match data.terminator().kind {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable

View File

@ -12,7 +12,7 @@ use crate::MemFlags;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
@ -178,7 +178,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
mir::UnwindAction::Terminate => {
mir::UnwindAction::Terminate(reason) => {
if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) {
// MSVC SEH will abort automatically if an exception tries to
// propagate out from cleanup.
@ -191,7 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
None
} else {
Some(fx.terminate_block())
Some(fx.terminate_block(reason))
}
}
};
@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
) -> MergingSucc {
let unwind_target = match unwind {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
mir::UnwindAction::Terminate => Some(fx.terminate_block()),
mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)),
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
};
@ -649,12 +649,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
helper: TerminatorCodegenHelper<'tcx>,
bx: &mut Bx,
terminator: &mir::Terminator<'tcx>,
reason: UnwindTerminateReason,
) {
let span = terminator.source_info.span;
self.set_debug_loc(bx, terminator.source_info);
// Obtain the panic entry point.
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item());
// Codegen the actual panic invoke/call.
let merging_succ = helper.do_call(
@ -1229,8 +1230,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
MergingSucc::False
}
mir::TerminatorKind::UnwindTerminate => {
self.codegen_terminate_terminator(helper, bx, terminator);
mir::TerminatorKind::UnwindTerminate(reason) => {
self.codegen_terminate_terminator(helper, bx, terminator, reason);
MergingSucc::False
}
@ -1579,79 +1580,83 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
})
}
fn terminate_block(&mut self) -> Bx::BasicBlock {
self.terminate_block.unwrap_or_else(|| {
let funclet;
let llbb;
let mut bx;
if base::wants_msvc_seh(self.cx.sess()) {
// This is a basic block that we're aborting the program for,
// notably in an `extern` function. These basic blocks are inserted
// so that we assert that `extern` functions do indeed not panic,
// and if they do we abort the process.
//
// On MSVC these are tricky though (where we're doing funclets). If
// we were to do a cleanuppad (like below) the normal functions like
// `longjmp` would trigger the abort logic, terminating the
// program. Instead we insert the equivalent of `catch(...)` for C++
// which magically doesn't trigger when `longjmp` files over this
// frame.
//
// Lots more discussion can be found on #48251 but this codegen is
// modeled after clang's for:
//
// try {
// foo();
// } catch (...) {
// bar();
// }
//
// which creates an IR snippet like
//
// cs_terminate:
// %cs = catchswitch within none [%cp_terminate] unwind to caller
// cp_terminate:
// %cp = catchpad within %cs [null, i32 64, null]
// ...
fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock {
if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup {
return bb;
}
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
let funclet;
let llbb;
let mut bx;
if base::wants_msvc_seh(self.cx.sess()) {
// This is a basic block that we're aborting the program for,
// notably in an `extern` function. These basic blocks are inserted
// so that we assert that `extern` functions do indeed not panic,
// and if they do we abort the process.
//
// On MSVC these are tricky though (where we're doing funclets). If
// we were to do a cleanuppad (like below) the normal functions like
// `longjmp` would trigger the abort logic, terminating the
// program. Instead we insert the equivalent of `catch(...)` for C++
// which magically doesn't trigger when `longjmp` files over this
// frame.
//
// Lots more discussion can be found on #48251 but this codegen is
// modeled after clang's for:
//
// try {
// foo();
// } catch (...) {
// bar();
// }
//
// which creates an IR snippet like
//
// cs_terminate:
// %cs = catchswitch within none [%cp_terminate] unwind to caller
// cp_terminate:
// %cp = catchpad within %cs [null, i32 64, null]
// ...
let mut cs_bx = Bx::build(self.cx, llbb);
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
// The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
bx = Bx::build(self.cx, cp_llbb);
let null =
bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));
let sixty_four = bx.const_i32(64);
funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
} else {
llbb = Bx::append_block(self.cx, self.llfn, "terminate");
bx = Bx::build(self.cx, llbb);
let mut cs_bx = Bx::build(self.cx, llbb);
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
let llpersonality = self.cx.eh_personality();
bx.filter_landing_pad(llpersonality);
// The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
bx = Bx::build(self.cx, cp_llbb);
let null =
bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));
let sixty_four = bx.const_i32(64);
funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
} else {
llbb = Bx::append_block(self.cx, self.llfn, "terminate");
bx = Bx::build(self.cx, llbb);
funclet = None;
}
let llpersonality = self.cx.eh_personality();
bx.filter_landing_pad(llpersonality);
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
funclet = None;
}
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind);
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
bx.do_not_inline(llret);
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
bx.unreachable();
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
bx.do_not_inline(llret);
self.terminate_block = Some(llbb);
llbb
})
bx.unreachable();
if reason == UnwindTerminateReason::InCleanup {
self.terminate_in_cleanup_block = Some(llbb);
}
llbb
}
/// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already

View File

@ -83,8 +83,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// Cached unreachable block
unreachable_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding block
terminate_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding (reason: InCleanup) block
terminate_in_cleanup_block: Option<Bx::BasicBlock>,
/// The location where each MIR arg/var/tmp/ret is stored. This is
/// usually an `PlaceRef` representing an alloca, but not always:
@ -174,7 +174,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let mut start_bx = Bx::build(cx, start_llbb);
if mir.basic_blocks.iter().any(|bb| {
bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate))
bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate(_)))
}) {
start_bx.set_personality_fn(cx.eh_personality());
}
@ -199,7 +199,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
personality_slot: None,
cached_llbbs,
unreachable_block: None,
terminate_block: None,
terminate_in_cleanup_block: None,
cleanup_kinds,
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),

View File

@ -756,6 +756,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
///
/// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
/// unwinding, and doing so is UB.
#[cold] // usually we have normal returns, not unwinding
pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
self.frame_mut().loc = match target {
mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
@ -763,9 +764,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir::UnwindAction::Unreachable => {
throw_ub_custom!(fluent::const_eval_unreachable_unwind);
}
mir::UnwindAction::Terminate => {
mir::UnwindAction::Terminate(reason) => {
self.frame_mut().loc = Right(self.frame_mut().body.span);
M::unwind_terminate(self)?;
M::unwind_terminate(self, reason)?;
// This might have pushed a new stack frame, or it terminated execution.
// Either way, `loc` will not be updated.
return Ok(());

View File

@ -222,7 +222,10 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
/// Called when unwinding reached a state where execution should be terminated.
fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
fn unwind_terminate(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
reason: mir::UnwindTerminateReason,
) -> InterpResult<'tcx>;
/// Called for all binary operations where the LHS has pointer type.
///
@ -462,6 +465,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Called immediately after a stack frame got popped, but before jumping back to the caller.
/// The `locals` have already been destroyed!
#[inline(always)]
fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
@ -501,7 +505,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
}
#[inline(always)]
fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
fn unwind_terminate(
_ecx: &mut InterpCx<$mir, $tcx, Self>,
_reason: mir::UnwindTerminateReason,
) -> InterpResult<$tcx> {
unreachable!("unwinding cannot happen during compile-time evaluation")
}

View File

@ -196,8 +196,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
UnwindTerminate => {
M::unwind_terminate(self)?;
UnwindTerminate(reason) => {
M::unwind_terminate(self, reason)?;
}
// When we encounter Resume, we've finished unwinding

View File

@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.check_op(ops::Generator(hir::GeneratorKind::Gen))
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
// Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
}

View File

@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
}
}
mir::TerminatorKind::UnwindTerminate
mir::TerminatorKind::UnwindTerminate(_)
| mir::TerminatorKind::Call { .. }
| mir::TerminatorKind::Assert { .. }
| mir::TerminatorKind::FalseEdge { .. }

View File

@ -10,8 +10,8 @@ use rustc_middle::mir::{
traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents,
START_BLOCK,
Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo,
VarDebugInfoContents, START_BLOCK,
};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
@ -274,7 +274,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
self.fail(location, "`UnwindAction::Continue` in no-unwind function");
}
}
UnwindAction::Unreachable | UnwindAction::Terminate => (),
UnwindAction::Terminate(UnwindTerminateReason::InCleanup) => {
if !is_cleanup {
self.fail(
location,
"`UnwindAction::Terminate(InCleanup)` in a non-cleanup block",
);
}
}
// These are allowed everywhere.
UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (),
}
}
}
@ -501,7 +510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
}
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
let bb = location.block;
if !self.body.basic_blocks[bb].is_cleanup {
self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block")
@ -1233,7 +1242,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| TerminatorKind::InlineAsm { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable => {}
}

View File

@ -238,6 +238,7 @@ language_item_table! {
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0);
/// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;

View File

@ -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(InCleanup)
terminate_in_cleanup_block: Option<BasicBlock>,
body_span: Span,
next_local: usize,
}
@ -29,19 +30,21 @@ impl<'tcx> MirPatch<'tcx> {
next_local: body.local_decls.len(),
resume_block: None,
unreachable_cleanup_block: None,
terminate_block: None,
terminate_in_cleanup_block: None,
body_span: body.span,
};
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,12 @@ 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 matches!(
block.terminator().kind,
TerminatorKind::UnwindTerminate(UnwindTerminateReason::InCleanup)
) && block.statements.is_empty()
{
result.terminate_in_cleanup_block = Some(bb);
continue;
}
}
@ -93,8 +100,8 @@ impl<'tcx> MirPatch<'tcx> {
bb
}
pub fn terminate_block(&mut self) -> BasicBlock {
if let Some(bb) = self.terminate_block {
pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup {
return bb;
}
@ -102,11 +109,13 @@ impl<'tcx> MirPatch<'tcx> {
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);
if reason == UnwindTerminateReason::InCleanup {
self.terminate_in_cleanup_block = Some(bb);
}
bb
}

View File

@ -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)]

View File

@ -1,3 +1,4 @@
use rustc_hir::LangItem;
use smallvec::SmallVec;
use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
@ -100,6 +101,32 @@ 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",
}
}
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 +183,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain((&[]).into_iter().copied())
}
UnwindResume
| UnwindTerminate
| UnwindTerminate(_)
| GeneratorDrop
| Return
| Unreachable
@ -198,7 +225,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain(&mut [])
}
UnwindResume
| UnwindTerminate
| UnwindTerminate(_)
| GeneratorDrop
| Return
| Unreachable
@ -215,7 +242,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -234,7 +261,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -271,18 +298,27 @@ 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 {
match self.unwind() {
// Not needed or included in successors
None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
Some(UnwindAction::Continue) => write!(fmt, "unwind continue"),
Some(UnwindAction::Unreachable) => write!(fmt, "unwind unreachable"),
Some(UnwindAction::Terminate(reason)) => {
write!(fmt, "unwind terminate ({})", reason.as_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 +327,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 +349,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_str())
}
Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
Unreachable => write!(fmt, "unreachable"),
Drop { place, .. } => write!(fmt, "drop({place:?})"),
@ -391,7 +430,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 +482,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 +526,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 +536,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 +548,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 +556,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 +570,7 @@ impl<'tcx> TerminatorKind<'tcx> {
unwind,
} => TerminatorEdges::AssignOnReturn {
return_: destination,
unwind,
cleanup: unwind.cleanup_block(),
place: CallReturnPlaces::InlineAsm(operands),
},

View File

@ -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 { .. } |

View File

@ -370,7 +370,7 @@ impl DropTree {
let terminator = TerminatorKind::Drop {
target: blocks[drop_data.1].unwrap(),
// The caller will handle this if needed.
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
place: drop_data.0.local.into(),
replace: false,
};
@ -1507,7 +1507,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Yield { .. }

View File

@ -186,7 +186,7 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
match self.body[bb].terminator().kind {
// These terminators return control flow to the caller.
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::Return

View File

@ -80,7 +80,7 @@ impl Unwind {
fn into_action(self) -> UnwindAction {
match self {
Unwind::To(bb) => UnwindAction::Cleanup(bb),
Unwind::InCleanup => UnwindAction::Terminate,
Unwind::InCleanup => UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
}
}

View File

@ -1,5 +1,5 @@
use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction,
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
};
use std::ops::RangeInclusive;
@ -486,10 +486,10 @@ impl Direction for Forward {
propagate(target, exit_state);
propagate(unwind, exit_state);
}
TerminatorEdges::AssignOnReturn { return_, unwind, place } => {
TerminatorEdges::AssignOnReturn { return_, cleanup, place } => {
// This must be done *first*, otherwise the unwind path will see the assignments.
if let UnwindAction::Cleanup(unwind) = unwind {
propagate(unwind, exit_state);
if let Some(cleanup) = cleanup {
propagate(cleanup, exit_state);
}
if let Some(return_) = return_ {
analysis.apply_call_return_effect(exit_state, bb, place);

View File

@ -131,7 +131,7 @@ where
}
}
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::FalseEdge { .. }

View File

@ -291,7 +291,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
// Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added.
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. }
@ -328,7 +328,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
// Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added.
TerminatorKind::Yield { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. }

View File

@ -371,7 +371,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// need recording.
| TerminatorKind::Return
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } => {}

View File

@ -270,7 +270,7 @@ pub trait ValueAnalysis<'tcx> {
}
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Assert { .. }

View File

@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
for id in calls_to_terminate {
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
*cleanup = UnwindAction::Terminate;
*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
}
for id in cleanups_to_remove {

View File

@ -53,8 +53,10 @@ impl AddCallGuards {
kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
source_info,
}) if pred_count[*destination] > 1
&& (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate)
|| self == &AllCallEdges) =>
&& (matches!(
unwind,
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_)
) || self == &AllCallEdges) =>
{
// It's a critical edge, break it
let call_guard = BasicBlockData {

View File

@ -58,7 +58,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
| TerminatorKind::Assert { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { .. }

View File

@ -679,7 +679,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
// None of these have Operands to const-propagate.
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -116,7 +116,7 @@ impl CoverageGraph {
match term.kind {
TerminatorKind::Return { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. } => {
// The `bb` has more than one _outgoing_ edge, or exits the function. Save the

View File

@ -868,7 +868,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
// Retain spans from all other terminators
TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop

View File

@ -648,7 +648,7 @@ impl WriteInfo {
}
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable { .. } => (),
TerminatorKind::Drop { .. } => {

View File

@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
UnwindAction::Unreachable => {
Unwind::To(self.patch.unreachable_cleanup_block())
}
UnwindAction::Terminate => {
Unwind::To(self.patch.terminate_block())
UnwindAction::Terminate(reason) => {
debug_assert_ne!(
reason,
UnwindTerminateReason::InCleanup,
"we are not in a cleanup block, InCleanup reason should be impossible"
);
Unwind::To(self.patch.terminate_block(reason))
}
}
};
@ -496,7 +501,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
if let TerminatorKind::Call {
destination,
target: Some(_),
unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate,
unwind:
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_),
..
} = data.terminator().kind
{

View File

@ -1091,7 +1091,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
UnwindAction::Cleanup(tgt) => tgt,
UnwindAction::Continue => elaborator.patch.resume_block(),
UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
UnwindAction::Terminate => elaborator.patch.terminate_block(),
UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason),
})
};
elaborate_drop(
@ -1239,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These never unwind.
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -1759,7 +1759,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -906,12 +906,12 @@ impl Integrator<'_, '_> {
UnwindAction::Cleanup(_) | UnwindAction::Continue => {
bug!("cleanup on cleanup block");
}
UnwindAction::Unreachable | UnwindAction::Terminate => return unwind,
UnwindAction::Unreachable | UnwindAction::Terminate(_) => return unwind,
}
}
match unwind {
UnwindAction::Unreachable | UnwindAction::Terminate => unwind,
UnwindAction::Unreachable | UnwindAction::Terminate(_) => unwind,
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
// Add an unwind edge to the original call's cleanup block
UnwindAction::Continue => self.cleanup_block,
@ -1022,10 +1022,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
UnwindAction::Continue => TerminatorKind::UnwindResume,
UnwindAction::Unreachable => TerminatorKind::Unreachable,
UnwindAction::Terminate => TerminatorKind::UnwindTerminate,
UnwindAction::Terminate(reason) => TerminatorKind::UnwindTerminate(reason),
};
}
TerminatorKind::UnwindTerminate => {}
TerminatorKind::UnwindTerminate(_) => {}
TerminatorKind::Unreachable => {}
TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
*real_target = self.map_block(*real_target);

View File

@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. }
| TerminatorKind::Return
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. }

View File

@ -114,7 +114,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
| TerminatorKind::Assert { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::InlineAsm { .. }
@ -166,7 +166,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
}
TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop

View File

@ -570,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> {
TerminatorKind::Drop {
place: dest_field,
target: unwind,
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false,
},
true,
/* is_cleanup */ true,
);
unwind = next_unwind;
}
@ -851,10 +851,10 @@ fn build_call_shim<'tcx>(
TerminatorKind::Drop {
place: rcvr_place(),
target: BasicBlock::new(4),
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false,
},
true,
/* is_cleanup */ true,
);
// BB #4 - resume

View File

@ -737,6 +737,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
let source = self.body.source_info(location).span;
let tcx = self.tcx;
let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
if should_codegen_locally(tcx, &instance) {
this.output.push(create_fn_mono_item(tcx, instance, source));
}
};
match terminator.kind {
mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx);
@ -771,19 +778,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
_ => LangItem::Panic,
};
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
push_mono_lang_item(self, lang_item);
}
mir::TerminatorKind::UnwindTerminate { .. } => {
let instance = Instance::mono(
tcx,
tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
mir::TerminatorKind::UnwindTerminate(reason) => {
push_mono_lang_item(self, reason.lang_item());
}
mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::SwitchInt { .. }
@ -796,14 +794,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
| mir::TerminatorKind::FalseUnwind { .. } => bug!(),
}
if let Some(mir::UnwindAction::Terminate) = terminator.unwind() {
let instance = Instance::mono(
tcx,
tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() {
push_mono_lang_item(self, reason.lang_item());
}
self.super_terminator(terminator, location);

View File

@ -590,7 +590,7 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction {
match self {
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable,
UnwindAction::Terminate => stable_mir::mir::UnwindAction::Terminate,
UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate,
UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()),
}
}
@ -788,7 +788,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
otherwise: targets.otherwise().as_usize(),
},
UnwindResume => Terminator::Resume,
UnwindTerminate => Terminator::Abort,
UnwindTerminate(_) => Terminator::Abort,
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
Drop { place, target, unwind, replace: _ } => Terminator::Drop {

View File

@ -1100,6 +1100,7 @@ symbols! {
panic_handler,
panic_impl,
panic_implementation,
panic_in_cleanup,
panic_info,
panic_location,
panic_misaligned_pointer_dereference,

View File

@ -179,6 +179,8 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
/// Panic because we cannot unwind out of a function.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
@ -189,6 +191,21 @@ fn panic_cannot_unwind() -> ! {
panic_nounwind("panic in a function that cannot unwind")
}
/// Panic because we are unwinding out of a destructor during cleanup.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg(not(bootstrap))]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_in_cleanup() -> ! {
panic_nounwind("panic in a destructor during cleanup")
}
/// This function is used instead of panic_fmt in const eval.
#[lang = "const_panic_fmt"]
#[rustc_const_unstable(feature = "core_panic", issue = "none")]

View File

@ -292,7 +292,7 @@ fn check_terminator<'tcx>(
| TerminatorKind::Goto { .. }
| TerminatorKind::Return
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable => Ok(()),
TerminatorKind::Drop { place, .. } => {
if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) {

View File

@ -975,9 +975,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
ecx.start_panic_nounwind(msg)
}
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> {
// Call the lang item.
let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap();
let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
ecx.call_function(
panic,

View File

@ -5,7 +5,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
second
stack backtrace:
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
panic in a destructor during cleanup
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
@ -20,7 +20,7 @@ LL | ABORT();
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/double_panic.rs:LL:CC
|

View File

@ -9,7 +9,7 @@ fn main() -> () {
bb0: {
StorageLive(_1);
_1 = const ();
asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate];
asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate (panic in a function that cannot unwind)];
}
bb1: {

View File

@ -47,7 +47,7 @@
bb2 (cleanup): {
_5 = move _6;
- drop(_6) -> [return: bb6, unwind terminate];
- drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb6;
}
@ -71,12 +71,12 @@
}
bb6 (cleanup): {
- drop(_5) -> [return: bb7, unwind terminate];
- drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb7;
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}

View File

@ -51,7 +51,7 @@ fn main() -> () {
bb2 (cleanup): {
_5 = move _6;
drop(_6) -> [return: bb6, unwind terminate];
drop(_6) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
}
bb3: {
@ -73,11 +73,11 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_5) -> [return: bb7, unwind terminate];
drop(_5) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)];
}
bb7 (cleanup): {
drop(_4) -> [return: bb8, unwind terminate];
drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
}
bb8 (cleanup): {

View File

@ -54,15 +54,15 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_7) -> [return: bb7, unwind terminate];
drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)];
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate];
drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb9 (cleanup): {

View File

@ -54,15 +54,15 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_7) -> [return: bb7, unwind terminate];
drop(_7) -> [return: bb7, unwind terminate (panic in a destructor during cleanup)];
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate];
drop(_1) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb9 (cleanup): {

View File

@ -62,7 +62,7 @@ fn droppy() -> () {
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -89,15 +89,15 @@ fn move_out_by_subslice() -> () {
}
bb9 (cleanup): {
drop(_1) -> [return: bb12, unwind terminate];
drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
}
bb10 (cleanup): {
drop(_7) -> [return: bb11, unwind terminate];
drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)];
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
}
bb12 (cleanup): {

View File

@ -89,15 +89,15 @@ fn move_out_from_end() -> () {
}
bb9 (cleanup): {
drop(_1) -> [return: bb12, unwind terminate];
drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
}
bb10 (cleanup): {
drop(_7) -> [return: bb11, unwind terminate];
drop(_7) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)];
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
}
bb12 (cleanup): {

View File

@ -63,7 +63,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -28,7 +28,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -28,7 +28,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -104,7 +104,7 @@ yields ()
bb13 (cleanup): {
StorageDead(_3);
drop(_1) -> [return: bb14, unwind terminate];
drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)];
}
bb14 (cleanup): {
@ -113,6 +113,6 @@ yields ()
bb15 (cleanup): {
StorageDead(_3);
drop(_1) -> [return: bb14, unwind terminate];
drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)];
}
}

View File

@ -17,7 +17,7 @@
StorageLive(_1);
- _1 = foo() -> [return: bb1, unwind unreachable];
+ StorageLive(_2);
+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate];
+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate (panic in a function that cannot unwind)];
}
bb1: {

View File

@ -32,7 +32,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -30,7 +30,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -36,7 +36,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -36,7 +36,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -27,7 +27,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -30,7 +30,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -54,11 +54,11 @@
+ }
+
+ bb4 (cleanup): {
+ drop(_4) -> [return: bb5, unwind terminate];
+ drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb5 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb6 (cleanup): {

View File

@ -37,7 +37,7 @@
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate];
drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -40,7 +40,7 @@
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate];
drop(_1) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
}
bb5 (cleanup): {

View File

@ -40,7 +40,7 @@
bb4 (cleanup): {
_8 = &mut _3;
_9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate];
_9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate (panic in a destructor during cleanup)];
}
}

View File

@ -40,17 +40,17 @@
}
bb3 (cleanup): {
- drop(_3) -> [return: bb5, unwind terminate];
- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5;
}
bb4 (cleanup): {
- drop(_4) -> [return: bb5, unwind terminate];
- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5;
}
bb5 (cleanup): {
- drop(_2) -> [return: bb6, unwind terminate];
- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
@ -59,7 +59,7 @@
+ }
+
+ bb7 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb8 (cleanup): {

View File

@ -40,17 +40,17 @@
}
bb3 (cleanup): {
- drop(_3) -> [return: bb5, unwind terminate];
- drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5;
}
bb4 (cleanup): {
- drop(_4) -> [return: bb5, unwind terminate];
- drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5;
}
bb5 (cleanup): {
- drop(_2) -> [return: bb6, unwind terminate];
- drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
@ -59,7 +59,7 @@
+ }
+
+ bb7 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb8 (cleanup): {

View File

@ -47,7 +47,7 @@
bb3 (cleanup): {
_2 = move _5;
- drop(_5) -> [return: bb8, unwind terminate];
- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
@ -70,17 +70,17 @@
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
bb8 (cleanup): {
- drop(_2) -> [return: bb9, unwind terminate];
- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb9;
}
bb9 (cleanup): {
- drop(_1) -> [return: bb10, unwind terminate];
- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb12;
}
@ -89,7 +89,7 @@
+ }
+
+ bb11 (cleanup): {
+ drop(_1) -> [return: bb10, unwind terminate];
+ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb12 (cleanup): {

View File

@ -47,7 +47,7 @@
bb3 (cleanup): {
_2 = move _5;
- drop(_5) -> [return: bb8, unwind terminate];
- drop(_5) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
@ -70,17 +70,17 @@
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8;
}
bb8 (cleanup): {
- drop(_2) -> [return: bb9, unwind terminate];
- drop(_2) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb9;
}
bb9 (cleanup): {
- drop(_1) -> [return: bb10, unwind terminate];
- drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb12;
}
@ -89,7 +89,7 @@
+ }
+
+ bb11 (cleanup): {
+ drop(_1) -> [return: bb10, unwind terminate];
+ drop(_1) -> [return: bb10, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb12 (cleanup): {

View File

@ -58,7 +58,7 @@
+ _8 = const true;
+ _9 = const true;
_1 = move _3;
- drop(_3) -> [return: bb11, unwind terminate];
- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb11;
}
@ -102,7 +102,7 @@
}
bb11 (cleanup): {
- drop(_1) -> [return: bb12, unwind terminate];
- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb12;
}
@ -124,7 +124,7 @@
+ }
+
+ bb16 (cleanup): {
+ drop(_1) -> [return: bb12, unwind terminate];
+ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb17: {

View File

@ -58,7 +58,7 @@
+ _8 = const true;
+ _9 = const true;
_1 = move _3;
- drop(_3) -> [return: bb11, unwind terminate];
- drop(_3) -> [return: bb11, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb11;
}
@ -102,7 +102,7 @@
}
bb11 (cleanup): {
- drop(_1) -> [return: bb12, unwind terminate];
- drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb12;
}
@ -124,7 +124,7 @@
+ }
+
+ bb16 (cleanup): {
+ drop(_1) -> [return: bb12, unwind terminate];
+ drop(_1) -> [return: bb12, unwind terminate (panic in a destructor during cleanup)];
+ }
+
+ bb17: {

View File

@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> {
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate];
drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)];
}
bb12 (cleanup): {
drop(_5) -> [return: bb13, unwind terminate];
drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)];
}
bb13 (cleanup): {

View File

@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> {
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate];
drop(_1) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)];
}
bb12 (cleanup): {
drop(_5) -> [return: bb13, unwind terminate];
drop(_5) -> [return: bb13, unwind terminate (panic in a destructor during cleanup)];
}
bb13 (cleanup): {

View File

@ -28,7 +28,7 @@ fn bar(_1: Box<[T]>) -> () {
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -45,7 +45,7 @@ fn foo(_1: Box<[T]>) -> T {
}
bb5 (cleanup): {
drop(_1) -> [return: bb6, unwind terminate];
drop(_1) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
}
bb6 (cleanup): {

View File

@ -243,7 +243,7 @@
}
- bb25 (cleanup): {
- drop(_2) -> [return: bb26, unwind terminate];
- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)];
+ bb22 (cleanup): {
+ goto -> bb27;
}

View File

@ -243,7 +243,7 @@
}
- bb25 (cleanup): {
- drop(_2) -> [return: bb26, unwind terminate];
- drop(_2) -> [return: bb26, unwind terminate (panic in a destructor during cleanup)];
+ bb22 (cleanup): {
+ goto -> bb27;
}

View File

@ -31,7 +31,7 @@ fn main() -> () {
}
bb3 (cleanup): {
drop(_2) -> [return: bb4, unwind terminate];
drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -31,7 +31,7 @@ fn main() -> () {
}
bb3 (cleanup): {
drop(_2) -> [return: bb4, unwind terminate];
drop(_2) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -33,7 +33,7 @@ fn main() -> () {
bb1 (cleanup): {
(_1.0: Aligned) = move _4;
drop(_1) -> [return: bb3, unwind terminate];
drop(_1) -> [return: bb3, unwind terminate (panic in a destructor during cleanup)];
}
bb2: {

View File

@ -167,11 +167,11 @@ fn main() -> () {
}
bb7 (cleanup): {
drop(_21) -> [return: bb9, unwind terminate];
drop(_21) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate (panic in a destructor during cleanup)];
}
bb9 (cleanup): {

View File

@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
bb3 (cleanup): {
_4 = &raw mut (*_1)[_3];
_3 = Add(move _3, const 1_usize);
drop((*_4)) -> [return: bb4, unwind terminate];
drop((*_4)) -> [return: bb4, unwind terminate (panic in a destructor during cleanup)];
}
bb4 (cleanup): {

View File

@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
}
bb4 (cleanup): {
drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate];
drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate (panic in a destructor during cleanup)];
}
bb5: {