Auto merge of #114993 - RalfJung:panic-nounwind, r=fee1-dead

interpret/miri: call the panic_nounwind machinery the same way codegen does
This commit is contained in:
bors 2023-08-20 22:01:18 +00:00
commit 5c6a7e71cd
66 changed files with 408 additions and 243 deletions

View File

@ -159,7 +159,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.mutate_place(location, *resume_arg, Deep); self.mutate_place(location, *resume_arg, Deep);
} }
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => { TerminatorKind::UnwindResume
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop => {
// Invalidate all borrows of local places // Invalidate all borrows of local places
let borrow_set = self.borrow_set; let borrow_set = self.borrow_set;
let start = self.location_table.start_index(location); let start = self.location_table.start_index(location);
@ -200,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
} }
} }
TerminatorKind::Goto { target: _ } TerminatorKind::Goto { target: _ }
| TerminatorKind::Terminate | 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,9 +770,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
} }
TerminatorKind::Goto { target: _ } TerminatorKind::Goto { target: _ }
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
@ -803,7 +803,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
} }
} }
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => { TerminatorKind::UnwindResume
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop => {
// Returning from the function implicitly kills storage for all locals and statics. // Returning from the function implicitly kills storage for all locals and statics.
// Often, the storage will already have been killed by an explicit // Often, the storage will already have been killed by an explicit
// StorageDead, but we don't always emit those (notably on unwind paths), // StorageDead, but we don't always emit those (notably on unwind paths),
@ -815,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
} }
} }
TerminatorKind::Terminate TerminatorKind::UnwindTerminate
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }

View File

@ -1333,8 +1333,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
debug!("terminator kind: {:?}", term.kind); debug!("terminator kind: {:?}", term.kind);
match &term.kind { match &term.kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
@ -1608,12 +1608,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.assert_iscleanup(body, block_data, *target, is_cleanup); self.assert_iscleanup(body, block_data, *target, is_cleanup);
} }
} }
TerminatorKind::Resume => { TerminatorKind::UnwindResume => {
if !is_cleanup { if !is_cleanup {
span_mirbug!(self, block_data, "resume on non-cleanup block!") span_mirbug!(self, block_data, "resume on non-cleanup block!")
} }
} }
TerminatorKind::Terminate => { 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!")
} }

View File

@ -474,10 +474,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
*destination, *destination,
); );
} }
TerminatorKind::Terminate => { TerminatorKind::UnwindTerminate => {
codegen_panic_cannot_unwind(fx, source_info); codegen_panic_cannot_unwind(fx, source_info);
} }
TerminatorKind::Resume => { TerminatorKind::UnwindResume => {
// FIXME implement unwinding // FIXME implement unwinding
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
} }

View File

@ -550,8 +550,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
match &bb_data.terminator().kind { match &bb_data.terminator().kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }

View File

@ -284,8 +284,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
for (bb, data) in mir.basic_blocks.iter_enumerated() { for (bb, data) in mir.basic_blocks.iter_enumerated() {
match data.terminator().kind { match data.terminator().kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable | TerminatorKind::Unreachable

View File

@ -1224,12 +1224,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.set_debug_loc(bx, terminator.source_info); self.set_debug_loc(bx, terminator.source_info);
match terminator.kind { match terminator.kind {
mir::TerminatorKind::Resume => { mir::TerminatorKind::UnwindResume => {
self.codegen_resume_terminator(helper, bx); self.codegen_resume_terminator(helper, bx);
MergingSucc::False MergingSucc::False
} }
mir::TerminatorKind::Terminate => { mir::TerminatorKind::UnwindTerminate => {
self.codegen_terminate_terminator(helper, bx, terminator); self.codegen_terminate_terminator(helper, bx, terminator);
MergingSucc::False MergingSucc::False
} }

View File

@ -18,7 +18,6 @@ pub enum ConstEvalErrKind {
ModifiedGlobal, ModifiedGlobal,
AssertFailure(AssertKind<ConstInt>), AssertFailure(AssertKind<ConstInt>),
Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
Abort(String),
} }
impl MachineStopType for ConstEvalErrKind { impl MachineStopType for ConstEvalErrKind {
@ -30,7 +29,6 @@ impl MachineStopType for ConstEvalErrKind {
ModifiedGlobal => const_eval_modified_global, ModifiedGlobal => const_eval_modified_global,
Panic { .. } => const_eval_panic, Panic { .. } => const_eval_panic,
AssertFailure(x) => x.diagnostic_message(), AssertFailure(x) => x.diagnostic_message(),
Abort(msg) => msg.to_string().into(),
} }
} }
fn add_args( fn add_args(
@ -39,7 +37,7 @@ impl MachineStopType for ConstEvalErrKind {
) { ) {
use ConstEvalErrKind::*; use ConstEvalErrKind::*;
match *self { match *self {
ConstAccessesStatic | ModifiedGlobal | Abort(_) => {} ConstAccessesStatic | ModifiedGlobal => {}
AssertFailure(kind) => kind.add_args(adder), AssertFailure(kind) => kind.add_args(adder),
Panic { msg, line, col, file } => { Panic { msg, line, col, file } => {
adder("msg".into(), msg.into_diagnostic_arg()); adder("msg".into(), msg.into_diagnostic_arg());

View File

@ -464,6 +464,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance))) Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
} }
fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
let msg = Symbol::intern(msg);
let span = ecx.find_closest_untracked_caller_location();
let (file, line, col) = ecx.location_triple_for_span(span);
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
}
fn call_intrinsic( fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>, ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
@ -584,10 +591,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Err(ConstEvalErrKind::AssertFailure(err).into()) Err(ConstEvalErrKind::AssertFailure(err).into())
} }
fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: String) -> InterpResult<'tcx, !> {
Err(ConstEvalErrKind::Abort(msg).into())
}
fn binary_ptr_op( fn binary_ptr_op(
_ecx: &InterpCx<'mir, 'tcx, Self>, _ecx: &InterpCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp, _bin_op: mir::BinOp,

View File

@ -765,7 +765,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
mir::UnwindAction::Terminate => { mir::UnwindAction::Terminate => {
self.frame_mut().loc = Right(self.frame_mut().body.span); self.frame_mut().loc = Right(self.frame_mut().body.span);
M::abort(self, "panic in a function that cannot unwind".to_owned())?; M::unwind_terminate(self)?;
// This might have pushed a new stack frame, or it terminated execution.
// Either way, `loc` will not be updated.
return Ok(());
} }
}; };
Ok(()) Ok(())
@ -865,6 +868,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
panic!("encountered StackPopCleanup::Root when unwinding!") panic!("encountered StackPopCleanup::Root when unwinding!")
} }
}; };
// This must be the very last thing that happens, since it can in fact push a new stack frame.
self.unwind_to_block(unwind) self.unwind_to_block(unwind)
} else { } else {
// Follow the normal return edge. // Follow the normal return edge.

View File

@ -125,15 +125,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, bool> { ) -> InterpResult<'tcx, bool> {
let instance_args = instance.args; let instance_args = instance.args;
let intrinsic_name = self.tcx.item_name(instance.def_id()); let intrinsic_name = self.tcx.item_name(instance.def_id());
let Some(ret) = ret else {
// First handle intrinsics without return place. // We don't support any intrinsic without return place.
let ret = match ret { return Ok(false);
None => match intrinsic_name {
sym::abort => M::abort(self, "the program aborted execution".to_owned())?,
// Unsupported diverging intrinsic.
_ => return Ok(false),
},
Some(p) => p,
}; };
match intrinsic_name { match intrinsic_name {
@ -410,7 +404,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"), ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
}; };
M::abort(self, msg)?; M::panic_nounwind(self, &msg)?;
// Skip the `go_to_block` at the end.
return Ok(true);
} }
} }
sym::simd_insert => { sym::simd_insert => {

View File

@ -218,10 +218,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
unwind: mir::UnwindAction, unwind: mir::UnwindAction,
) -> InterpResult<'tcx>; ) -> InterpResult<'tcx>;
/// Called to abort evaluation. /// Called to trigger a non-unwinding panic.
fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> { fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
throw_unsup_format!("aborting execution is not supported")
} /// Called when unwinding reached a state where execution should be terminated.
fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
/// Called for all binary operations where the LHS has pointer type. /// Called for all binary operations where the LHS has pointer type.
/// ///
@ -499,6 +500,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
false false
} }
#[inline(always)]
fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
unreachable!("unwinding cannot happen during compile-time evaluation")
}
#[inline(always)] #[inline(always)]
fn call_extra_fn( fn call_extra_fn(
_ecx: &mut InterpCx<$mir, $tcx, Self>, _ecx: &mut InterpCx<$mir, $tcx, Self>,

View File

@ -196,15 +196,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
} }
Terminate => { UnwindTerminate => {
// FIXME: maybe should call `panic_no_unwind` lang item instead. M::unwind_terminate(self)?;
M::abort(self, "panic in a function that cannot unwind".to_owned())?;
} }
// When we encounter Resume, we've finished unwinding // When we encounter Resume, we've finished unwinding
// cleanup for the current stack frame. We pop it in order // cleanup for the current stack frame. We pop it in order
// to continue unwinding the next frame // to continue unwinding the next frame
Resume => { UnwindResume => {
trace!("unwinding: resuming from cleanup"); trace!("unwinding: resuming from cleanup");
// By definition, a Resume terminator means // By definition, a Resume terminator means
// that we're unwinding // that we're 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::Terminate => { 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")
} }
@ -1046,7 +1046,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Unreachable => {} | TerminatorKind::Unreachable => {}

View File

@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
} }
} }
mir::TerminatorKind::Terminate mir::TerminatorKind::UnwindTerminate
| mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Call { .. }
| mir::TerminatorKind::Assert { .. } | mir::TerminatorKind::Assert { .. }
| mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseEdge { .. }
@ -114,7 +114,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
| mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::GeneratorDrop
| mir::TerminatorKind::Goto { .. } | mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::InlineAsm { .. } | mir::TerminatorKind::InlineAsm { .. }
| mir::TerminatorKind::Resume | mir::TerminatorKind::UnwindResume
| mir::TerminatorKind::Return | mir::TerminatorKind::Return
| mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::SwitchInt { .. }
| mir::TerminatorKind::Unreachable | mir::TerminatorKind::Unreachable

View File

@ -492,19 +492,19 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
); );
} }
} }
TerminatorKind::Resume => { TerminatorKind::UnwindResume => {
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 `Resume` from non-cleanup basic block") self.fail(location, "Cannot `UnwindResume` from non-cleanup basic block")
} }
if !self.can_unwind { if !self.can_unwind {
self.fail(location, "Cannot `Resume` in a function that cannot unwind") self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
} }
} }
TerminatorKind::Terminate => { 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 `Terminate` from non-cleanup basic block") self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block")
} }
} }
TerminatorKind::Return => { TerminatorKind::Return => {
@ -1232,8 +1232,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. } | TerminatorKind::InlineAsm { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable => {} | TerminatorKind::Unreachable => {}
} }

View File

@ -35,7 +35,7 @@ impl<'tcx> MirPatch<'tcx> {
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::Resume = block.terminator().kind && block.statements.is_empty() { if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() {
result.resume_block = Some(bb); result.resume_block = Some(bb);
continue; continue;
} }
@ -50,7 +50,7 @@ impl<'tcx> MirPatch<'tcx> {
} }
// Check if we already have a terminate block // Check if we already have a terminate block
if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() { if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() {
result.terminate_block = Some(bb); result.terminate_block = Some(bb);
continue; continue;
} }
@ -68,7 +68,7 @@ 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::Resume, kind: TerminatorKind::UnwindResume,
}), }),
is_cleanup: true, is_cleanup: true,
}); });
@ -102,7 +102,7 @@ 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::Terminate, kind: TerminatorKind::UnwindTerminate,
}), }),
is_cleanup: true, is_cleanup: true,
}); });

View File

@ -238,45 +238,6 @@ pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1) format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
} }
pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
use StatementKind::*;
match statement.kind {
Assign(..) => "Assign",
FakeRead(..) => "FakeRead",
SetDiscriminant { .. } => "SetDiscriminant",
Deinit(..) => "Deinit",
StorageLive(..) => "StorageLive",
StorageDead(..) => "StorageDead",
Retag(..) => "Retag",
PlaceMention(..) => "PlaceMention",
AscribeUserType(..) => "AscribeUserType",
Coverage(..) => "Coverage",
Intrinsic(..) => "Intrinsic",
ConstEvalCounter => "ConstEvalCounter",
Nop => "Nop",
}
}
pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
use TerminatorKind::*;
match term.kind {
Goto { .. } => "Goto",
SwitchInt { .. } => "SwitchInt",
Resume => "Resume",
Terminate => "Terminate",
Return => "Return",
Unreachable => "Unreachable",
Drop { .. } => "Drop",
Call { .. } => "Call",
Assert { .. } => "Assert",
Yield { .. } => "Yield",
GeneratorDrop => "GeneratorDrop",
FalseEdge { .. } => "FalseEdge",
FalseUnwind { .. } => "FalseUnwind",
InlineAsm { .. } => "InlineAsm",
}
}
fn statement_span_viewable<'tcx>( fn statement_span_viewable<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body_span: Span, body_span: Span,
@ -304,7 +265,7 @@ fn terminator_span_viewable<'tcx>(
if !body_span.contains(span) { if !body_span.contains(span) {
return None; return None;
} }
let id = format!("{}:{}", bb.index(), terminator_kind_name(term)); let id = format!("{}:{}", bb.index(), term.kind.name());
let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator); let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator);
Some(SpanViewable { bb, span, id, tooltip }) Some(SpanViewable { bb, span, id, tooltip })
} }
@ -631,7 +592,7 @@ fn tooltip<'tcx>(
"\n{}{}: {}: {:?}", "\n{}{}: {}: {:?}",
TOOLTIP_INDENT, TOOLTIP_INDENT,
source_range, source_range,
statement_kind_name(&statement), statement.kind.name(),
statement statement
)); ));
} }
@ -641,7 +602,7 @@ fn tooltip<'tcx>(
"\n{}{}: {}: {:?}", "\n{}{}: {}: {:?}",
TOOLTIP_INDENT, TOOLTIP_INDENT,
source_range, source_range,
terminator_kind_name(term), term.kind.name(),
term.kind term.kind
)); ));
} }

View File

@ -380,6 +380,28 @@ pub enum StatementKind<'tcx> {
Nop, Nop,
} }
impl StatementKind<'_> {
/// Returns a simple string representation of a `StatementKind` variant, independent of any
/// values it might hold (e.g. `StatementKind::Assign` always returns `"Assign"`).
pub const fn name(&self) -> &'static str {
match self {
StatementKind::Assign(..) => "Assign",
StatementKind::FakeRead(..) => "FakeRead",
StatementKind::SetDiscriminant { .. } => "SetDiscriminant",
StatementKind::Deinit(..) => "Deinit",
StatementKind::StorageLive(..) => "StorageLive",
StatementKind::StorageDead(..) => "StorageDead",
StatementKind::Retag(..) => "Retag",
StatementKind::PlaceMention(..) => "PlaceMention",
StatementKind::AscribeUserType(..) => "AscribeUserType",
StatementKind::Coverage(..) => "Coverage",
StatementKind::Intrinsic(..) => "Intrinsic",
StatementKind::ConstEvalCounter => "ConstEvalCounter",
StatementKind::Nop => "Nop",
}
}
}
#[derive( #[derive(
Clone, Clone,
TyEncodable, TyEncodable,
@ -593,13 +615,13 @@ pub enum TerminatorKind<'tcx> {
/// ///
/// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
/// deaggregation runs. /// deaggregation runs.
Resume, UnwindResume,
/// Indicates that the landing pad is finished and that the process should terminate. /// Indicates that the landing pad is finished and that the process should terminate.
/// ///
/// 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.
Terminate, UnwindTerminate,
/// Returns from the function. /// Returns from the function.
/// ///
@ -790,8 +812,8 @@ impl TerminatorKind<'_> {
match self { match self {
TerminatorKind::Goto { .. } => "Goto", TerminatorKind::Goto { .. } => "Goto",
TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::SwitchInt { .. } => "SwitchInt",
TerminatorKind::Resume => "Resume", TerminatorKind::UnwindResume => "UnwindResume",
TerminatorKind::Terminate => "Terminate", TerminatorKind::UnwindTerminate => "UnwindTerminate",
TerminatorKind::Return => "Return", TerminatorKind::Return => "Return",
TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Unreachable => "Unreachable",
TerminatorKind::Drop { .. } => "Drop", TerminatorKind::Drop { .. } => "Drop",

View File

@ -155,8 +155,8 @@ impl<'tcx> TerminatorKind<'tcx> {
| InlineAsm { destination: Some(t), unwind: _, .. } => { | InlineAsm { destination: Some(t), unwind: _, .. } => {
Some(t).into_iter().chain((&[]).into_iter().copied()) Some(t).into_iter().chain((&[]).into_iter().copied())
} }
Resume UnwindResume
| Terminate | UnwindTerminate
| GeneratorDrop | GeneratorDrop
| Return | Return
| Unreachable | Unreachable
@ -197,8 +197,8 @@ impl<'tcx> TerminatorKind<'tcx> {
| InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
Some(t).into_iter().chain(&mut []) Some(t).into_iter().chain(&mut [])
} }
Resume UnwindResume
| Terminate | UnwindTerminate
| GeneratorDrop | GeneratorDrop
| Return | Return
| Unreachable | Unreachable
@ -214,8 +214,8 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn unwind(&self) -> Option<&UnwindAction> { pub fn unwind(&self) -> Option<&UnwindAction> {
match *self { match *self {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -233,8 +233,8 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> { pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
match *self { match *self {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -311,8 +311,8 @@ impl<'tcx> TerminatorKind<'tcx> {
SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"), SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"),
Return => write!(fmt, "return"), Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"), GeneratorDrop => write!(fmt, "generator_drop"),
Resume => write!(fmt, "resume"), UnwindResume => write!(fmt, "resume"),
Terminate => write!(fmt, "abort"), UnwindTerminate => write!(fmt, "abort"),
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 +391,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 | Resume | Terminate | 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
@ -486,7 +486,9 @@ 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 | Resume | Terminate | GeneratorDrop | Unreachable => TerminatorEdges::None, Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => {
TerminatorEdges::None
}
Goto { target } => TerminatorEdges::Single(target), Goto { target } => TerminatorEdges::Single(target),

View File

@ -469,8 +469,8 @@ macro_rules! make_mir_visitor {
self.visit_source_info(source_info); self.visit_source_info(source_info);
match kind { match kind {
TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. } |
TerminatorKind::Resume | TerminatorKind::UnwindResume |
TerminatorKind::Terminate | TerminatorKind::UnwindTerminate |
TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable | TerminatorKind::Unreachable |
TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. } |

View File

@ -685,9 +685,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
drops.add_entry(block, drop_idx); drops.add_entry(block, drop_idx);
// `build_drop_trees` doesn't have access to our source_info, so we // `build_drop_trees` doesn't have access to our source_info, so we
// create a dummy terminator now. `TerminatorKind::Resume` is used // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
// because MIR type checking will panic if it hasn't been overwritten. // because MIR type checking will panic if it hasn't been overwritten.
self.cfg.terminate(block, source_info, TerminatorKind::Resume); self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
self.cfg.start_new_block().unit() self.cfg.start_new_block().unit()
} }
@ -717,9 +717,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
drops.add_entry(block, drop_idx); drops.add_entry(block, drop_idx);
// `build_drop_trees` doesn't have access to our source_info, so we // `build_drop_trees` doesn't have access to our source_info, so we
// create a dummy terminator now. `TerminatorKind::Resume` is used // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
// because MIR type checking will panic if it hasn't been overwritten. // because MIR type checking will panic if it hasn't been overwritten.
self.cfg.terminate(block, source_info, TerminatorKind::Resume); self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
} }
// Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue` // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
@ -1441,7 +1441,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
blocks[ROOT_NODE] = *resume_block; blocks[ROOT_NODE] = *resume_block;
drops.build_mir::<Unwind>(cfg, &mut blocks); drops.build_mir::<Unwind>(cfg, &mut blocks);
if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) { if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::Resume); cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);
*resume_block = blocks[ROOT_NODE]; *resume_block = blocks[ROOT_NODE];
} }
@ -1506,8 +1506,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
} }
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }

View File

@ -186,9 +186,9 @@ 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::Terminate TerminatorKind::UnwindTerminate
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive), | TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),

View File

@ -131,7 +131,7 @@ where
} }
} }
TerminatorKind::Terminate TerminatorKind::UnwindTerminate
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
@ -139,7 +139,7 @@ where
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::InlineAsm { .. } | TerminatorKind::InlineAsm { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Unreachable | TerminatorKind::Unreachable

View File

@ -291,14 +291,14 @@ 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::Terminate TerminatorKind::UnwindTerminate
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Unreachable => {} | TerminatorKind::Unreachable => {}
@ -328,14 +328,14 @@ 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::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Unreachable => {} | TerminatorKind::Unreachable => {}

View File

@ -370,8 +370,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// this that could possibly access the return place, this doesn't // this that could possibly access the return place, this doesn't
// need recording. // need recording.
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } => {} | TerminatorKind::Drop { .. } => {}

View File

@ -269,8 +269,8 @@ pub trait ValueAnalysis<'tcx> {
return self.handle_switch_int(discr, targets, state); return self.handle_switch_int(discr, targets, state);
} }
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }

View File

@ -57,8 +57,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View File

@ -180,6 +180,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
throw_machine_stop_str!("calling functions isn't supported in ConstProp") throw_machine_stop_str!("calling functions isn't supported in ConstProp")
} }
fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &str) -> InterpResult<'tcx> {
throw_machine_stop_str!("panicking isn't supported in ConstProp")
}
fn find_mir_or_eval_fn( fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_instance: ty::Instance<'tcx>, _instance: ty::Instance<'tcx>,

View File

@ -678,8 +678,8 @@ 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::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | 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::Terminate | 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
@ -146,7 +146,7 @@ impl CoverageGraph {
// is as intended. (See Issue #78544 for a possible future option to support // is as intended. (See Issue #78544 for a possible future option to support
// coverage in test programs that panic.) // coverage in test programs that panic.)
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }

View File

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

View File

@ -541,6 +541,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
unimplemented!() unimplemented!()
} }
fn panic_nounwind(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_msg: &str,
) -> interpret::InterpResult<'tcx> {
unimplemented!()
}
fn call_intrinsic( fn call_intrinsic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_instance: ty::Instance<'tcx>, _instance: ty::Instance<'tcx>,

View File

@ -647,8 +647,8 @@ impl WriteInfo {
} }
} }
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable { .. } => (), | TerminatorKind::Unreachable { .. } => (),
TerminatorKind::Drop { .. } => { TerminatorKind::Drop { .. } => {

View File

@ -470,7 +470,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// drop elaboration should handle that by itself // drop elaboration should handle that by itself
continue; continue;
} }
TerminatorKind::Resume => { TerminatorKind::UnwindResume => {
// It is possible for `Resume` to be patched // It is possible for `Resume` to be patched
// (in particular it can be patched to be replaced with // (in particular it can be patched to be replaced with
// a Goto; see `MirPatch::new`). // a Goto; see `MirPatch::new`).

View File

@ -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::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -1248,7 +1248,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// Resume will *continue* unwinding, but if there's no other unwinding terminator it // Resume will *continue* unwinding, but if there's no other unwinding terminator it
// will never be reached. // will never be reached.
TerminatorKind::Resume => {} TerminatorKind::UnwindResume => {}
TerminatorKind::Yield { .. } => { TerminatorKind::Yield { .. } => {
unreachable!("`can_unwind` called before generator transform") unreachable!("`can_unwind` called before generator transform")
@ -1279,14 +1279,14 @@ fn create_generator_resume_function<'tcx>(
let source_info = SourceInfo::outermost(body.span); let source_info = SourceInfo::outermost(body.span);
let poison_block = body.basic_blocks_mut().push(BasicBlockData { let poison_block = body.basic_blocks_mut().push(BasicBlockData {
statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }),
is_cleanup: true, is_cleanup: true,
}); });
for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() { for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
let source_info = block.terminator().source_info; let source_info = block.terminator().source_info;
if let TerminatorKind::Resume = block.terminator().kind { if let TerminatorKind::UnwindResume = block.terminator().kind {
// An existing `Resume` terminator is redirected to jump to our dedicated // An existing `Resume` terminator is redirected to jump to our dedicated
// "poisoning block" above. // "poisoning block" above.
if idx != poison_block { if idx != poison_block {
@ -1758,8 +1758,8 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
TerminatorKind::Call { .. } TerminatorKind::Call { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }

View File

@ -839,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
self.cost += LANDINGPAD_PENALTY; self.cost += LANDINGPAD_PENALTY;
} }
} }
TerminatorKind::Resume => self.cost += RESUME_PENALTY, TerminatorKind::UnwindResume => self.cost += RESUME_PENALTY,
TerminatorKind::InlineAsm { unwind, .. } => { TerminatorKind::InlineAsm { unwind, .. } => {
self.cost += INSTR_COST; self.cost += INSTR_COST;
if let UnwindAction::Cleanup(_) = unwind { if let UnwindAction::Cleanup(_) = unwind {
@ -1017,15 +1017,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::Unreachable TerminatorKind::Unreachable
} }
} }
TerminatorKind::Resume => { TerminatorKind::UnwindResume => {
terminator.kind = match self.cleanup_block { terminator.kind = match self.cleanup_block {
UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt }, UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
UnwindAction::Continue => TerminatorKind::Resume, UnwindAction::Continue => TerminatorKind::UnwindResume,
UnwindAction::Unreachable => TerminatorKind::Unreachable, UnwindAction::Unreachable => TerminatorKind::Unreachable,
UnwindAction::Terminate => TerminatorKind::Terminate, UnwindAction::Terminate => TerminatorKind::UnwindTerminate,
}; };
} }
TerminatorKind::Terminate => {} 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

@ -63,7 +63,7 @@ impl RemoveNoopLandingPads {
let terminator = body[bb].terminator(); let terminator = body[bb].terminator();
match terminator.kind { match terminator.kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => { | TerminatorKind::FalseUnwind { .. } => {
@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
TerminatorKind::GeneratorDrop TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
@ -88,7 +88,7 @@ impl RemoveNoopLandingPads {
let has_resume = body let has_resume = body
.basic_blocks .basic_blocks
.iter_enumerated() .iter_enumerated()
.any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::Resume)); .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
if !has_resume { if !has_resume {
debug!("remove_noop_landing_pads: no resume block in MIR"); debug!("remove_noop_landing_pads: no resume block in MIR");
return; return;

View File

@ -108,13 +108,13 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
} }
// The following terminators are not allowed // The following terminators are not allowed
TerminatorKind::Resume TerminatorKind::UnwindResume
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::InlineAsm { .. } | TerminatorKind::InlineAsm { .. }
@ -165,8 +165,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
}); });
} }
TerminatorKind::Resume TerminatorKind::UnwindResume
| TerminatorKind::Terminate | TerminatorKind::UnwindTerminate
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop

View File

@ -583,7 +583,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
I: IntoIterator<Item = Ty<'tcx>>, I: IntoIterator<Item = Ty<'tcx>>,
{ {
self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false); self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
let unwind = self.block(vec![], TerminatorKind::Resume, true); let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
let target = self.block(vec![], TerminatorKind::Return, false); let target = self.block(vec![], TerminatorKind::Return, false);
let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys); let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
@ -597,7 +597,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
args: GeneratorArgs<'tcx>, args: GeneratorArgs<'tcx>,
) { ) {
self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false); self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
let unwind = self.block(vec![], TerminatorKind::Resume, true); let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
// This will get overwritten with a switch once we know the target blocks // This will get overwritten with a switch once we know the target blocks
let switch = self.block(vec![], TerminatorKind::Unreachable, false); let switch = self.block(vec![], TerminatorKind::Unreachable, false);
let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys()); let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
@ -854,7 +854,7 @@ fn build_call_shim<'tcx>(
); );
// BB #4 - resume // BB #4 - resume
block(&mut blocks, vec![], TerminatorKind::Resume, true); block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
} }
let mut body = let mut body =

View File

@ -776,7 +776,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
self.output.push(create_fn_mono_item(tcx, instance, source)); self.output.push(create_fn_mono_item(tcx, instance, source));
} }
} }
mir::TerminatorKind::Terminate { .. } => { mir::TerminatorKind::UnwindTerminate { .. } => {
let instance = Instance::mono( let instance = Instance::mono(
tcx, tcx,
tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
@ -787,7 +787,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
} }
mir::TerminatorKind::Goto { .. } mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::SwitchInt { .. }
| mir::TerminatorKind::Resume | mir::TerminatorKind::UnwindResume
| mir::TerminatorKind::Return | mir::TerminatorKind::Return
| mir::TerminatorKind::Unreachable => {} | mir::TerminatorKind::Unreachable => {}
mir::TerminatorKind::GeneratorDrop mir::TerminatorKind::GeneratorDrop

View File

@ -780,8 +780,8 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
.collect(), .collect(),
otherwise: targets.otherwise().as_usize(), otherwise: targets.otherwise().as_usize(),
}, },
Resume => Terminator::Resume, UnwindResume => Terminator::Resume,
Terminate => 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

@ -291,8 +291,8 @@ fn check_terminator<'tcx>(
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Terminate | 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

@ -971,9 +971,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
ecx.assert_panic(msg, unwind) ecx.assert_panic(msg, unwind)
} }
#[inline(always)] fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
fn abort(_ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: String) -> InterpResult<'tcx, !> { ecx.start_panic_nounwind(msg)
throw_machine_stop!(TerminationInfo::Abort(msg)) }
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
// Call the lang item.
let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
ecx.call_function(
panic,
Abi::Rust,
&[],
None,
StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
)?;
Ok(())
} }
#[inline(always)] #[inline(always)]

View File

@ -34,10 +34,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
if this.emulate_intrinsic(instance, args, dest, ret)? { if this.emulate_intrinsic(instance, args, dest, ret)? {
return Ok(()); return Ok(());
} }
// All remaining supported intrinsics have a return place.
let intrinsic_name = this.tcx.item_name(instance.def_id()); let intrinsic_name = this.tcx.item_name(instance.def_id());
let intrinsic_name = intrinsic_name.as_str(); let intrinsic_name = intrinsic_name.as_str();
// Handle intrinsics without return place.
match intrinsic_name {
"abort" => {
throw_machine_stop!(TerminationInfo::Abort(
"the program aborted execution".to_owned()
))
}
_ => {},
}
// All remaining supported intrinsics have a return place.
let ret = match ret { let ret = match ret {
None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"), None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"),
Some(p) => p, Some(p) => p,
@ -393,7 +403,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"breakpoint" => { "breakpoint" => {
let [] = check_arg_count(args)?; let [] = check_arg_count(args)?;
// normally this would raise a SIGTRAP, which aborts if no debugger is connected // normally this would raise a SIGTRAP, which aborts if no debugger is connected
throw_machine_stop!(TerminationInfo::Abort(format!("Trace/breakpoint trap"))) throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
} }
name => throw_unsup_format!("unimplemented intrinsic: `{name}`"), name => throw_unsup_format!("unimplemented intrinsic: `{name}`"),

View File

@ -188,6 +188,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) )
} }
/// Start a non-unwinding panic in the interpreter with the given message as payload.
fn start_panic_nounwind(&mut self, msg: &str) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
// First arg: message.
let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?;
// Call the lang item.
let panic = this.tcx.lang_items().panic_nounwind().unwrap();
let panic = ty::Instance::mono(this.tcx.tcx, panic);
this.call_function(
panic,
Abi::Rust,
&[msg.to_ref(this)],
None,
StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
)
}
fn assert_panic( fn assert_panic(
&mut self, &mut self,
msg: &mir::AssertMessage<'tcx>, msg: &mir::AssertMessage<'tcx>,

View File

@ -2,6 +2,6 @@
fn main() { fn main() {
unsafe { unsafe {
core::intrinsics::breakpoint() //~ ERROR: Trace/breakpoint trap core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
}; };
} }

View File

@ -1,8 +1,8 @@
error: abnormal termination: Trace/breakpoint trap error: abnormal termination: trace/breakpoint trap
--> $DIR/breakpoint.rs:LL:CC --> $DIR/breakpoint.rs:LL:CC
| |
LL | core::intrinsics::breakpoint() LL | core::intrinsics::breakpoint()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Trace/breakpoint trap | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
| |
= note: inside `main` at $DIR/breakpoint.rs:LL:CC = note: inside `main` at $DIR/breakpoint.rs:LL:CC

View File

@ -1,22 +1,35 @@
thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
explicit panic explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `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 `nounwind`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |
LL | / extern "C-unwind" fn nounwind() { LL | / extern "C-unwind" fn nounwind() {
LL | |
LL | |
LL | | panic!(); LL | | panic!();
LL | | } LL | | }
| |_^ panic in a function that cannot unwind | |_^
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
note: inside `main` note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |
LL | unsafe { nounwind() } LL | unsafe { nounwind() }
| ^^^^^^^^^^ | ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,22 +1,35 @@
thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
explicit panic explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `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 `nounwind`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |
LL | / extern "C-unwind" fn nounwind() { LL | / extern "C-unwind" fn nounwind() {
LL | |
LL | |
LL | | panic!(); LL | | panic!();
LL | | } LL | | }
| |_^ panic in a function that cannot unwind | |_^
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
note: inside `main` note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |
LL | unsafe { nounwind() } LL | unsafe { nounwind() }
| ^^^^^^^^^^ | ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -5,7 +5,7 @@ error: Undefined Behavior: unwinding past a stack frame that does not allow unwi
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
| |
LL | unsafe { nounwind() } LL | unsafe { nounwind() }
| ^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding | ^ unwinding past a stack frame that does not allow unwinding
| |
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -1,11 +1,14 @@
//@revisions: extern_block definition both //@revisions: extern_block definition both
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@[definition,both]error-in-other-file: aborted execution
#![feature(rustc_attrs, c_unwind)] #![feature(rustc_attrs, c_unwind)]
#[cfg_attr(any(definition, both), rustc_nounwind)] #[cfg_attr(any(definition, both), rustc_nounwind)]
#[no_mangle] #[no_mangle]
extern "C-unwind" fn nounwind() { extern "C-unwind" fn nounwind() {
//~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind
//~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind
panic!(); panic!();
} }

View File

@ -1,7 +1,11 @@
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
#![feature(never_type)] #![feature(never_type)]
#[allow(deprecated, invalid_value)] #[allow(deprecated, invalid_value)]
fn main() { fn main() {
let _ = unsafe { std::mem::uninitialized::<!>() }; let _ = unsafe { std::mem::uninitialized::<!>() };
//~^ ERROR: attempted to instantiate uninhabited type `!`
} }

View File

@ -1,10 +1,24 @@
error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!` thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
aborted execution: attempted to instantiate uninhabited type `!`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/uninit_uninhabited_type.rs:LL:CC --> $DIR/uninit_uninhabited_type.rs:LL:CC
| |
LL | let _ = unsafe { std::mem::uninitialized::<!>() }; LL | let _ = unsafe { std::mem::uninitialized::<!>() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | ^
|
= note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,5 +1,10 @@
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
#[allow(deprecated, invalid_value)] #[allow(deprecated, invalid_value)]
fn main() { fn main() {
let _ = unsafe { std::mem::zeroed::<fn()>() }; let _ = unsafe { std::mem::zeroed::<fn()>() };
//~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid
} }

View File

@ -1,10 +1,24 @@
error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
aborted execution: attempted to zero-initialize type `fn()`, which is invalid
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/zero_fn_ptr.rs:LL:CC --> $DIR/zero_fn_ptr.rs:LL:CC
| |
LL | let _ = unsafe { std::mem::zeroed::<fn()>() }; LL | let _ = unsafe { std::mem::zeroed::<fn()>() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid | ^
|
= note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,6 +1,8 @@
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1" //@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
struct Foo; struct Foo;
impl Drop for Foo { impl Drop for Foo {
@ -9,7 +11,6 @@ impl Drop for Foo {
} }
} }
fn main() { fn main() {
//~^ERROR: panic in a function that cannot unwind
let _foo = Foo; let _foo = Foo;
panic!("first"); panic!("first");
} }

View File

@ -4,17 +4,31 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at $DIR/double_panic.rs:LL:CC: thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
second second
stack backtrace: stack backtrace:
error: abnormal termination: panic in a function that cannot unwind thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `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 `main`
--> $DIR/double_panic.rs:LL:CC --> $DIR/double_panic.rs:LL:CC
| |
LL | / fn main() { LL | / fn main() {
LL | |
LL | | let _foo = Foo; LL | | let _foo = Foo;
LL | | panic!("first"); LL | | panic!("first");
LL | | } LL | | }
| |_^ panic in a function that cannot unwind | |_^
|
= note: inside `main` at $DIR/double_panic.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,5 +1,10 @@
//@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000 //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000
// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
//@error-in-other-file: aborted execution
// Enable MIR inlining to ensure that `TerminatorKind::UnwindTerminate` is generated
// instead of just `UnwindAction::Terminate`. // instead of just `UnwindAction::Terminate`.
#![feature(c_unwind)] #![feature(c_unwind)]
@ -12,7 +17,6 @@ impl Drop for Foo {
#[inline(always)] #[inline(always)]
fn has_cleanup() { fn has_cleanup() {
//~^ ERROR: panic in a function that cannot unwind
let _f = Foo; let _f = Foo;
panic!(); panic!();
} }

View File

@ -3,27 +3,41 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul
thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC: thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC:
explicit panic explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `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 `has_cleanup`
--> $DIR/terminate-terminator.rs:LL:CC --> $DIR/terminate-terminator.rs:LL:CC
| |
LL | / fn has_cleanup() { LL | / fn has_cleanup() {
LL | |
LL | | let _f = Foo; LL | | let _f = Foo;
LL | | panic!(); LL | | panic!();
LL | | } LL | | }
| |_^ panic in a function that cannot unwind | |_^
|
= note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
note: inside `panic_abort` note: inside `panic_abort`
--> $DIR/terminate-terminator.rs:LL:CC --> $DIR/terminate-terminator.rs:LL:CC
| |
LL | has_cleanup(); LL | has_cleanup();
| ^^^^^^^^^^^^^ | ^
note: inside `main` note: inside `main`
--> $DIR/terminate-terminator.rs:LL:CC --> $DIR/terminate-terminator.rs:LL:CC
| |
LL | panic_abort(); LL | panic_abort();
| ^^^^^^^^^^^^^ | ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,7 +1,11 @@
//@error-in-other-file: aborted execution
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"
//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
#![feature(c_unwind)] #![feature(c_unwind)]
extern "C" fn panic_abort() { extern "C" fn panic_abort() {
//~^ ERROR: panic in a function that cannot unwind
panic!() panic!()
} }

View File

@ -1,21 +1,35 @@
thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC: thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC:
explicit panic explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: abnormal termination: panic in a function that cannot unwind thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
--> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
|
LL | ABORT();
| ^ the program aborted execution
|
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.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 `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 `panic_abort`
--> $DIR/unwind-action-terminate.rs:LL:CC --> $DIR/unwind-action-terminate.rs:LL:CC
| |
LL | / extern "C" fn panic_abort() { LL | / extern "C" fn panic_abort() {
LL | |
LL | | panic!() LL | | panic!()
LL | | } LL | | }
| |_^ panic in a function that cannot unwind | |_^
|
= note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
note: inside `main` note: inside `main`
--> $DIR/unwind-action-terminate.rs:LL:CC --> $DIR/unwind-action-terminate.rs:LL:CC
| |
LL | panic_abort(); LL | panic_abort();
| ^^^^^^^^^^^^^ | ^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -368,7 +368,7 @@ pub enum TerminatorKind {
/// ///
/// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
/// deaggregation runs. /// deaggregation runs.
Resume, UnwindResume,
/// Indicates that the landing pad is finished and that the process should abort. /// Indicates that the landing pad is finished and that the process should abort.
/// ///
@ -1057,7 +1057,7 @@ impl MirBody {
TerminatorKind::FalseEdge { .. } TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return

View File

@ -160,7 +160,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
TerminatorKind::FalseEdge { .. } TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
@ -280,7 +280,7 @@ fn ever_initialized_map(
let targets = match &terminator.kind { let targets = match &terminator.kind {
TerminatorKind::Goto { target } => vec![*target], TerminatorKind::Goto { target } => vec![*target],
TerminatorKind::SwitchInt { targets, .. } => targets.all_targets().to_vec(), TerminatorKind::SwitchInt { targets, .. } => targets.all_targets().to_vec(),
TerminatorKind::Resume TerminatorKind::UnwindResume
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable => vec![], | TerminatorKind::Unreachable => vec![],
@ -371,7 +371,7 @@ fn mutability_of_locals(
}; };
match &terminator.kind { match &terminator.kind {
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable

View File

@ -265,7 +265,7 @@ impl Filler<'_> {
self.fill_operand(discr)?; self.fill_operand(discr)?;
} }
TerminatorKind::Goto { .. } TerminatorKind::Goto { .. }
| TerminatorKind::Resume | TerminatorKind::UnwindResume
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable

View File

@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:12:9 --> $DIR/assert-type-intrinsics.rs:12:9
| |
LL | MaybeUninit::<!>::uninit().assume_init(); LL | MaybeUninit::<!>::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:16:9 --> $DIR/assert-type-intrinsics.rs:16:9
| |
LL | intrinsics::assert_mem_uninitialized_valid::<&'static i32>(); LL | intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:20:9 --> $DIR/assert-type-intrinsics.rs:20:9
| |
LL | intrinsics::assert_zero_valid::<&'static i32>(); LL | intrinsics::assert_zero_valid::<&'static i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9
error: aborting due to 3 previous errors error: aborting due to 3 previous errors