1
Fork 0

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::Goto { target: _ }
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { | 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::Goto { target: _ }
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::Return | 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::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }

View file

@ -1334,7 +1334,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match &term.kind { match &term.kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, block_data, "resume on non-cleanup block!") span_mirbug!(self, block_data, "resume on non-cleanup block!")
} }
} }
TerminatorKind::UnwindTerminate => { TerminatorKind::UnwindTerminate(_) => {
if !is_cleanup { if !is_cleanup {
span_mirbug!(self, block_data, "abort on non-cleanup block!") 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") 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, *destination,
); );
} }
TerminatorKind::UnwindTerminate => { TerminatorKind::UnwindTerminate(reason) => {
codegen_panic_cannot_unwind(fx, source_info); codegen_unwind_terminate(fx, source_info, *reason);
} }
TerminatorKind::UnwindResume => { TerminatorKind::UnwindResume => {
// FIXME implement unwinding // 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); 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>, fx: &mut FunctionCx<'_, '_, 'tcx>,
source_info: mir::SourceInfo, source_info: mir::SourceInfo,
reason: UnwindTerminateReason,
) { ) {
let args = []; 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>( fn codegen_panic_inner<'tcx>(

View file

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

View file

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

View file

@ -12,7 +12,7 @@ use crate::MemFlags;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem; 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::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty}; 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::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
mir::UnwindAction::Continue => None, mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => 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) { 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 // MSVC SEH will abort automatically if an exception tries to
// propagate out from cleanup. // propagate out from cleanup.
@ -191,7 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
None None
} else { } else {
Some(fx.terminate_block()) Some(fx.terminate_block(reason))
} }
} }
}; };
@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
) -> MergingSucc { ) -> MergingSucc {
let unwind_target = match unwind { let unwind_target = match unwind {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), 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::Continue => None,
mir::UnwindAction::Unreachable => None, mir::UnwindAction::Unreachable => None,
}; };
@ -649,12 +649,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
helper: TerminatorCodegenHelper<'tcx>, helper: TerminatorCodegenHelper<'tcx>,
bx: &mut Bx, bx: &mut Bx,
terminator: &mir::Terminator<'tcx>, terminator: &mir::Terminator<'tcx>,
reason: UnwindTerminateReason,
) { ) {
let span = terminator.source_info.span; let span = terminator.source_info.span;
self.set_debug_loc(bx, terminator.source_info); self.set_debug_loc(bx, terminator.source_info);
// Obtain the panic entry point. // 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. // Codegen the actual panic invoke/call.
let merging_succ = helper.do_call( let merging_succ = helper.do_call(
@ -1229,8 +1230,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
MergingSucc::False MergingSucc::False
} }
mir::TerminatorKind::UnwindTerminate => { mir::TerminatorKind::UnwindTerminate(reason) => {
self.codegen_terminate_terminator(helper, bx, terminator); self.codegen_terminate_terminator(helper, bx, terminator, reason);
MergingSucc::False MergingSucc::False
} }
@ -1579,79 +1580,83 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}) })
} }
fn terminate_block(&mut self) -> Bx::BasicBlock { fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock {
self.terminate_block.unwrap_or_else(|| { if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup {
let funclet; return bb;
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]
// ...
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); let funclet;
let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); 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); llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
// The "null" here is actually a RTTI type descriptor for the let mut cs_bx = Bx::build(self.cx, llbb);
// C++ personality function, but `catch (...)` has no type so let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
// 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 llpersonality = self.cx.eh_personality(); // The "null" here is actually a RTTI type descriptor for the
bx.filter_landing_pad(llpersonality); // 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); self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
bx.do_not_inline(llret); 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); bx.unreachable();
llbb
}) if reason == UnwindTerminateReason::InCleanup {
self.terminate_in_cleanup_block = Some(llbb);
}
llbb
} }
/// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already /// 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 /// Cached unreachable block
unreachable_block: Option<Bx::BasicBlock>, unreachable_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding block /// Cached terminate upon unwinding (reason: InCleanup) block
terminate_block: Option<Bx::BasicBlock>, terminate_in_cleanup_block: Option<Bx::BasicBlock>,
/// The location where each MIR arg/var/tmp/ret is stored. This is /// The location where each MIR arg/var/tmp/ret is stored. This is
/// usually an `PlaceRef` representing an alloca, but not always: /// 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); let mut start_bx = Bx::build(cx, start_llbb);
if mir.basic_blocks.iter().any(|bb| { 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()); 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, personality_slot: None,
cached_llbbs, cached_llbbs,
unreachable_block: None, unreachable_block: None,
terminate_block: None, terminate_in_cleanup_block: None,
cleanup_kinds, cleanup_kinds,
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), 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 /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
/// unwinding, and doing so is UB. /// 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> { pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
self.frame_mut().loc = match target { self.frame_mut().loc = match target {
mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), 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 => { mir::UnwindAction::Unreachable => {
throw_ub_custom!(fluent::const_eval_unreachable_unwind); 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); 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. // This might have pushed a new stack frame, or it terminated execution.
// Either way, `loc` will not be updated. // Either way, `loc` will not be updated.
return Ok(()); 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>; fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
/// Called when unwinding reached a state where execution should be terminated. /// 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. /// 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. /// Called immediately after a stack frame got popped, but before jumping back to the caller.
/// The `locals` have already been destroyed! /// The `locals` have already been destroyed!
#[inline(always)]
fn after_stack_pop( fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, _frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
@ -501,7 +505,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
} }
#[inline(always)] #[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") 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 => { UnwindTerminate(reason) => {
M::unwind_terminate(self)?; M::unwind_terminate(self, reason)?;
} }
// When we encounter Resume, we've finished unwinding // 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)) self.check_op(ops::Generator(hir::GeneratorKind::Gen))
} }
TerminatorKind::UnwindTerminate => { TerminatorKind::UnwindTerminate(_) => {
// Cleanup blocks are skipped for const checking (see `visit_basic_block_data`). // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
span_bug!(self.span, "`Terminate` terminator outside of cleanup block") 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::Call { .. }
| mir::TerminatorKind::Assert { .. } | mir::TerminatorKind::Assert { .. }
| mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseEdge { .. }

View file

@ -10,8 +10,8 @@ use rustc_middle::mir::{
traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef, MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo,
START_BLOCK, VarDebugInfoContents, START_BLOCK,
}; };
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive; 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"); 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") self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
} }
} }
TerminatorKind::UnwindTerminate => { TerminatorKind::UnwindTerminate(_) => {
let bb = location.block; let bb = location.block;
if !self.body.basic_blocks[bb].is_cleanup { if !self.body.basic_blocks[bb].is_cleanup {
self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block") 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::InlineAsm { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable => {} | TerminatorKind::Unreachable => {}
} }

View file

@ -238,6 +238,7 @@ language_item_table! {
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, 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); 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 /// 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; 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>, resume_block: Option<BasicBlock>,
// Only for unreachable in cleanup path. // Only for unreachable in cleanup path.
unreachable_cleanup_block: Option<BasicBlock>, unreachable_cleanup_block: Option<BasicBlock>,
terminate_block: Option<BasicBlock>, // Cached block for UnwindTerminate(InCleanup)
terminate_in_cleanup_block: Option<BasicBlock>,
body_span: Span, body_span: Span,
next_local: usize, next_local: usize,
} }
@ -29,19 +30,21 @@ impl<'tcx> MirPatch<'tcx> {
next_local: body.local_decls.len(), next_local: body.local_decls.len(),
resume_block: None, resume_block: None,
unreachable_cleanup_block: None, unreachable_cleanup_block: None,
terminate_block: None, terminate_in_cleanup_block: None,
body_span: body.span, body_span: body.span,
}; };
for (bb, block) in body.basic_blocks.iter_enumerated() { for (bb, block) in body.basic_blocks.iter_enumerated() {
// Check if we already have a resume block // 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); result.resume_block = Some(bb);
continue; continue;
} }
// Check if we already have an unreachable block // 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.statements.is_empty()
&& block.is_cleanup && block.is_cleanup
{ {
@ -50,8 +53,12 @@ impl<'tcx> MirPatch<'tcx> {
} }
// Check if we already have a terminate block // Check if we already have a terminate block
if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() { if matches!(
result.terminate_block = Some(bb); block.terminator().kind,
TerminatorKind::UnwindTerminate(UnwindTerminateReason::InCleanup)
) && block.statements.is_empty()
{
result.terminate_in_cleanup_block = Some(bb);
continue; continue;
} }
} }
@ -93,8 +100,8 @@ impl<'tcx> MirPatch<'tcx> {
bb bb
} }
pub fn terminate_block(&mut self) -> BasicBlock { pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
if let Some(bb) = self.terminate_block { if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup {
return bb; return bb;
} }
@ -102,11 +109,13 @@ impl<'tcx> MirPatch<'tcx> {
statements: vec![], statements: vec![],
terminator: Some(Terminator { terminator: Some(Terminator {
source_info: SourceInfo::outermost(self.body_span), source_info: SourceInfo::outermost(self.body_span),
kind: TerminatorKind::UnwindTerminate, kind: TerminatorKind::UnwindTerminate(reason),
}), }),
is_cleanup: true, is_cleanup: true,
}); });
self.terminate_block = Some(bb); if reason == UnwindTerminateReason::InCleanup {
self.terminate_in_cleanup_block = Some(bb);
}
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 /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
/// cleanup blocks. /// cleanup blocks.
UnwindTerminate, UnwindTerminate(UnwindTerminateReason),
/// Returns from the function. /// Returns from the function.
/// ///
@ -813,7 +813,7 @@ impl TerminatorKind<'_> {
TerminatorKind::Goto { .. } => "Goto", TerminatorKind::Goto { .. } => "Goto",
TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::SwitchInt { .. } => "SwitchInt",
TerminatorKind::UnwindResume => "UnwindResume", TerminatorKind::UnwindResume => "UnwindResume",
TerminatorKind::UnwindTerminate => "UnwindTerminate", TerminatorKind::UnwindTerminate(_) => "UnwindTerminate",
TerminatorKind::Return => "Return", TerminatorKind::Return => "Return",
TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Unreachable => "Unreachable",
TerminatorKind::Drop { .. } => "Drop", TerminatorKind::Drop { .. } => "Drop",
@ -842,11 +842,22 @@ pub enum UnwindAction {
/// Terminates the execution if unwind happens. /// Terminates the execution if unwind happens.
/// ///
/// Depending on the platform and situation this may cause a non-unwindable panic or abort. /// Depending on the platform and situation this may cause a non-unwindable panic or abort.
Terminate, Terminate(UnwindTerminateReason),
/// Cleanups to be done. /// Cleanups to be done.
Cleanup(BasicBlock), 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. /// Information about an assertion failure.
#[derive(Clone, Hash, HashStable, PartialEq, Debug)] #[derive(Clone, Hash, HashStable, PartialEq, Debug)]
#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]

View file

@ -1,3 +1,4 @@
use rustc_hir::LangItem;
use smallvec::SmallVec; use smallvec::SmallVec;
use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction}; 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<'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)] #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct Terminator<'tcx> { pub struct Terminator<'tcx> {
pub source_info: SourceInfo, pub source_info: SourceInfo,
@ -156,7 +183,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain((&[]).into_iter().copied()) Some(t).into_iter().chain((&[]).into_iter().copied())
} }
UnwindResume UnwindResume
| UnwindTerminate | UnwindTerminate(_)
| GeneratorDrop | GeneratorDrop
| Return | Return
| Unreachable | Unreachable
@ -198,7 +225,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain(&mut []) Some(t).into_iter().chain(&mut [])
} }
UnwindResume UnwindResume
| UnwindTerminate | UnwindTerminate(_)
| GeneratorDrop | GeneratorDrop
| Return | Return
| Unreachable | Unreachable
@ -215,7 +242,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self { match *self {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -234,7 +261,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self { match *self {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -271,18 +298,27 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
let labels = self.fmt_successor_labels(); let labels = self.fmt_successor_labels();
assert_eq!(successor_count, labels.len()); assert_eq!(successor_count, labels.len());
let unwind = match self.unwind() { // `Cleanup` is already included in successors
// Not needed or included in successors let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_)));
None | Some(UnwindAction::Cleanup(_)) => None, let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result {
Some(UnwindAction::Continue) => Some("unwind continue"), match self.unwind() {
Some(UnwindAction::Unreachable) => Some("unwind unreachable"), // Not needed or included in successors
Some(UnwindAction::Terminate) => Some("unwind terminate"), 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) { match (successor_count, show_unwind) {
(0, None) => Ok(()), (0, false) => Ok(()),
(0, Some(unwind)) => write!(fmt, " -> {unwind}"), (0, true) => {
(1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), write!(fmt, " -> ")?;
fmt_unwind(fmt)
}
(1, false) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
_ => { _ => {
write!(fmt, " -> [")?; write!(fmt, " -> [")?;
for (i, target) in self.successors().enumerate() { for (i, target) in self.successors().enumerate() {
@ -291,8 +327,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
} }
write!(fmt, "{}: {:?}", labels[i], target)?; write!(fmt, "{}: {:?}", labels[i], target)?;
} }
if let Some(unwind) = unwind { if show_unwind {
write!(fmt, ", {unwind}")?; write!(fmt, ", ")?;
fmt_unwind(fmt)?;
} }
write!(fmt, "]") write!(fmt, "]")
} }
@ -312,7 +349,9 @@ impl<'tcx> TerminatorKind<'tcx> {
Return => write!(fmt, "return"), Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"), GeneratorDrop => write!(fmt, "generator_drop"),
UnwindResume => write!(fmt, "resume"), 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:?})"), Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
Unreachable => write!(fmt, "unreachable"), Unreachable => write!(fmt, "unreachable"),
Drop { place, .. } => write!(fmt, "drop({place:?})"), Drop { place, .. } => write!(fmt, "drop({place:?})"),
@ -391,7 +430,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
use self::TerminatorKind::*; use self::TerminatorKind::*;
match *self { match *self {
Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![], Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()], Goto { .. } => vec!["".into()],
SwitchInt { ref targets, .. } => targets SwitchInt { ref targets, .. } => targets
.values .values
@ -443,7 +482,8 @@ pub enum TerminatorEdges<'mir, 'tcx> {
/// Special action for `Yield`, `Call` and `InlineAsm` terminators. /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
AssignOnReturn { AssignOnReturn {
return_: Option<BasicBlock>, return_: Option<BasicBlock>,
unwind: UnwindAction, /// The cleanup block, if it exists.
cleanup: Option<BasicBlock>,
place: CallReturnPlaces<'mir, 'tcx>, place: CallReturnPlaces<'mir, 'tcx>,
}, },
/// Special edge for `SwitchInt`. /// Special edge for `SwitchInt`.
@ -486,7 +526,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> { pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
use TerminatorKind::*; use TerminatorKind::*;
match *self { match *self {
Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => { Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => {
TerminatorEdges::None TerminatorEdges::None
} }
@ -496,7 +536,7 @@ impl<'tcx> TerminatorKind<'tcx> {
| Drop { target, unwind, place: _, replace: _ } | Drop { target, unwind, place: _, replace: _ }
| FalseUnwind { real_target: target, unwind } => match unwind { | FalseUnwind { real_target: target, unwind } => match unwind {
UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind), UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => { UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => {
TerminatorEdges::Single(target) TerminatorEdges::Single(target)
} }
}, },
@ -508,7 +548,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Yield { resume: target, drop, resume_arg, value: _ } => { Yield { resume: target, drop, resume_arg, value: _ } => {
TerminatorEdges::AssignOnReturn { TerminatorEdges::AssignOnReturn {
return_: Some(target), return_: Some(target),
unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup), cleanup: drop,
place: CallReturnPlaces::Yield(resume_arg), place: CallReturnPlaces::Yield(resume_arg),
} }
} }
@ -516,7 +556,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
TerminatorEdges::AssignOnReturn { TerminatorEdges::AssignOnReturn {
return_: target, return_: target,
unwind, cleanup: unwind.cleanup_block(),
place: CallReturnPlaces::Call(destination), place: CallReturnPlaces::Call(destination),
} }
} }
@ -530,7 +570,7 @@ impl<'tcx> TerminatorKind<'tcx> {
unwind, unwind,
} => TerminatorEdges::AssignOnReturn { } => TerminatorEdges::AssignOnReturn {
return_: destination, return_: destination,
unwind, cleanup: unwind.cleanup_block(),
place: CallReturnPlaces::InlineAsm(operands), place: CallReturnPlaces::InlineAsm(operands),
}, },

View file

@ -470,7 +470,7 @@ macro_rules! make_mir_visitor {
match kind { match kind {
TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. } |
TerminatorKind::UnwindResume | TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_) |
TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable | TerminatorKind::Unreachable |
TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. } |

View file

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

View file

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

View file

@ -80,7 +80,7 @@ impl Unwind {
fn into_action(self) -> UnwindAction { fn into_action(self) -> UnwindAction {
match self { match self {
Unwind::To(bb) => UnwindAction::Cleanup(bb), 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::{ use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction, self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
}; };
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
@ -486,10 +486,10 @@ impl Direction for Forward {
propagate(target, exit_state); propagate(target, exit_state);
propagate(unwind, 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. // This must be done *first*, otherwise the unwind path will see the assignments.
if let UnwindAction::Cleanup(unwind) = unwind { if let Some(cleanup) = cleanup {
propagate(unwind, exit_state); propagate(cleanup, exit_state);
} }
if let Some(return_) = return_ { if let Some(return_) = return_ {
analysis.apply_call_return_effect(exit_state, bb, place); analysis.apply_call_return_effect(exit_state, bb, place);

View file

@ -131,7 +131,7 @@ where
} }
} }
TerminatorKind::UnwindTerminate TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::FalseEdge { .. } | 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 // Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added. // variants are added.
TerminatorKind::UnwindTerminate TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. } | 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 // Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added. // variants are added.
TerminatorKind::Yield { .. } TerminatorKind::Yield { .. }
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View file

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

View file

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

View file

@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
for id in calls_to_terminate { for id in calls_to_terminate {
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); 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 { for id in cleanups_to_remove {

View file

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

View file

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

View file

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

View file

@ -116,7 +116,7 @@ impl CoverageGraph {
match term.kind { match term.kind {
TerminatorKind::Return { .. } TerminatorKind::Return { .. }
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. } => { | TerminatorKind::SwitchInt { .. } => {
// The `bb` has more than one _outgoing_ edge, or exits the function. Save the // 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 // Retain spans from all other terminators
TerminatorKind::UnwindResume TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop

View file

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

View file

@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
UnwindAction::Unreachable => { UnwindAction::Unreachable => {
Unwind::To(self.patch.unreachable_cleanup_block()) Unwind::To(self.patch.unreachable_cleanup_block())
} }
UnwindAction::Terminate => { UnwindAction::Terminate(reason) => {
Unwind::To(self.patch.terminate_block()) 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 { if let TerminatorKind::Call {
destination, destination,
target: Some(_), target: Some(_),
unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate, unwind:
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_),
.. ..
} = data.terminator().kind } = 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::Cleanup(tgt) => tgt,
UnwindAction::Continue => elaborator.patch.resume_block(), UnwindAction::Continue => elaborator.patch.resume_block(),
UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(), UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
UnwindAction::Terminate => elaborator.patch.terminate_block(), UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason),
}) })
}; };
elaborate_drop( elaborate_drop(
@ -1239,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These never unwind. // These never unwind.
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -1759,7 +1759,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }

View file

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

View file

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

View file

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

View file

@ -570,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> {
TerminatorKind::Drop { TerminatorKind::Drop {
place: dest_field, place: dest_field,
target: unwind, target: unwind,
unwind: UnwindAction::Terminate, unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false, replace: false,
}, },
true, /* is_cleanup */ true,
); );
unwind = next_unwind; unwind = next_unwind;
} }
@ -851,10 +851,10 @@ fn build_call_shim<'tcx>(
TerminatorKind::Drop { TerminatorKind::Drop {
place: rcvr_place(), place: rcvr_place(),
target: BasicBlock::new(4), target: BasicBlock::new(4),
unwind: UnwindAction::Terminate, unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false, replace: false,
}, },
true, /* is_cleanup */ true,
); );
// BB #4 - resume // 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 source = self.body.source_info(location).span;
let tcx = self.tcx; 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 { match terminator.kind {
mir::TerminatorKind::Call { ref func, .. } => { mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx); 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, mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
_ => LangItem::Panic, _ => LangItem::Panic,
}; };
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); push_mono_lang_item(self, lang_item);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
} }
mir::TerminatorKind::UnwindTerminate { .. } => { mir::TerminatorKind::UnwindTerminate(reason) => {
let instance = Instance::mono( push_mono_lang_item(self, reason.lang_item());
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::Goto { .. } mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::SwitchInt { .. }
@ -796,14 +794,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
| mir::TerminatorKind::FalseUnwind { .. } => bug!(), | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
} }
if let Some(mir::UnwindAction::Terminate) = terminator.unwind() { if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() {
let instance = Instance::mono( push_mono_lang_item(self, reason.lang_item());
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));
}
} }
self.super_terminator(terminator, location); self.super_terminator(terminator, location);

View file

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

View file

@ -1100,6 +1100,7 @@ symbols! {
panic_handler, panic_handler,
panic_impl, panic_impl,
panic_implementation, panic_implementation,
panic_in_cleanup,
panic_info, panic_info,
panic_location, panic_location,
panic_misaligned_pointer_dereference, 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. /// 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 /// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller). /// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[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_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. /// This function is used instead of panic_fmt in const eval.
#[lang = "const_panic_fmt"] #[lang = "const_panic_fmt"]
#[rustc_const_unstable(feature = "core_panic", issue = "none")] #[rustc_const_unstable(feature = "core_panic", issue = "none")]

View file

@ -292,7 +292,7 @@ fn check_terminator<'tcx>(
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable => Ok(()), | TerminatorKind::Unreachable => Ok(()),
TerminatorKind::Drop { place, .. } => { TerminatorKind::Drop { place, .. } => {
if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { 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) 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. // 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); let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
ecx.call_function( ecx.call_function(
panic, panic,

View file

@ -5,7 +5,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
second second
stack backtrace: stack backtrace:
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: 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: stack backtrace:
thread caused non-unwinding panic. aborting. thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution 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::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 `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_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` note: inside `main`
--> $DIR/double_panic.rs:LL:CC --> $DIR/double_panic.rs:LL:CC
| |

View file

@ -9,7 +9,7 @@ fn main() -> () {
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
_1 = const (); _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: { bb1: {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -104,7 +104,7 @@ yields ()
bb13 (cleanup): { bb13 (cleanup): {
StorageDead(_3); StorageDead(_3);
drop(_1) -> [return: bb14, unwind terminate]; drop(_1) -> [return: bb14, unwind terminate (panic in a destructor during cleanup)];
} }
bb14 (cleanup): { bb14 (cleanup): {
@ -113,6 +113,6 @@ yields ()
bb15 (cleanup): { bb15 (cleanup): {
StorageDead(_3); 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); StorageLive(_1);
- _1 = foo() -> [return: bb1, unwind unreachable]; - _1 = foo() -> [return: bb1, unwind unreachable];
+ StorageLive(_2); + 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: { bb1: {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -40,7 +40,7 @@
bb4 (cleanup): { bb4 (cleanup): {
_8 = &mut _3; _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): { bb3 (cleanup): {
- drop(_3) -> [return: bb5, unwind terminate]; - drop(_3) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5; + goto -> bb5;
} }
bb4 (cleanup): { bb4 (cleanup): {
- drop(_4) -> [return: bb5, unwind terminate]; - drop(_4) -> [return: bb5, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb5; + goto -> bb5;
} }
bb5 (cleanup): { bb5 (cleanup): {
- drop(_2) -> [return: bb6, unwind terminate]; - drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ goto -> bb8; + goto -> bb8;
} }
@ -59,7 +59,7 @@
+ } + }
+ +
+ bb7 (cleanup): { + bb7 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate]; + drop(_2) -> [return: bb6, unwind terminate (panic in a destructor during cleanup)];
+ } + }
+ +
+ bb8 (cleanup): { + bb8 (cleanup): {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
bb3 (cleanup): { bb3 (cleanup): {
_4 = &raw mut (*_1)[_3]; _4 = &raw mut (*_1)[_3];
_3 = Add(move _3, const 1_usize); _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): { bb4 (cleanup): {

View file

@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
} }
bb4 (cleanup): { 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: { bb5: {