Prereq2 for async drop - ResumedAfterDrop panic messages

This commit is contained in:
Andrew Zhogin 2024-08-26 18:16:42 +03:00
parent e8f28c1a6c
commit a858408a28
12 changed files with 132 additions and 48 deletions

View File

@ -502,6 +502,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
ResumedAfterReturn(coroutine_kind) => ResumedAfterReturn(*coroutine_kind),
ResumedAfterPanic(coroutine_kind) => ResumedAfterPanic(*coroutine_kind),
ResumedAfterDrop(coroutine_kind) => ResumedAfterDrop(*coroutine_kind),
MisalignedPointerDereference { ref required, ref found } => {
MisalignedPointerDereference {
required: eval_to_int(required)?,

View File

@ -317,6 +317,10 @@ language_item_table! {
PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None;
PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None;
PanicAsyncGenFnResumedDrop, sym::panic_const_async_gen_fn_resumed_drop, panic_const_async_gen_fn_resumed_drop, Target::Fn, GenericRequirement::None;
PanicGenFnNoneDrop, sym::panic_const_gen_fn_none_drop, panic_const_gen_fn_none_drop, Target::Fn, GenericRequirement::None;
/// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;

View File

@ -1,10 +1,14 @@
middle_adjust_for_foreign_abi_error =
target architecture {$arch} does not support `extern {$abi}` ABI
middle_assert_async_resume_after_drop = `async fn` resumed after async drop
middle_assert_async_resume_after_panic = `async fn` resumed after panicking
middle_assert_async_resume_after_return = `async fn` resumed after completion
middle_assert_coroutine_resume_after_drop = coroutine resumed after async drop
middle_assert_coroutine_resume_after_panic = coroutine resumed after panicking
middle_assert_coroutine_resume_after_return = coroutine resumed after completion
@ -12,6 +16,8 @@ middle_assert_coroutine_resume_after_return = coroutine resumed after completion
middle_assert_divide_by_zero =
attempt to divide `{$val}` by zero
middle_assert_gen_resume_after_drop = `gen` fn or block cannot be further iterated on after it async dropped
middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked
middle_assert_misaligned_ptr_deref =

View File

@ -1104,6 +1104,7 @@ pub enum AssertKind<O> {
RemainderByZero(O),
ResumedAfterReturn(CoroutineKind),
ResumedAfterPanic(CoroutineKind),
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: O, found: O },
NullPointerDereference,
}

View File

@ -207,6 +207,16 @@ impl<O> AssertKind<O> {
LangItem::PanicGenFnNonePanic
}
NullPointerDereference => LangItem::PanicNullPointerDereference,
ResumedAfterDrop(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedDrop,
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
LangItem::PanicAsyncFnResumedDrop
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
LangItem::PanicAsyncGenFnResumedDrop
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
LangItem::PanicGenFnNoneDrop
}
BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
bug!("Unexpected AssertKind")
@ -297,6 +307,18 @@ impl<O> AssertKind<O> {
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
write!(f, "\"`gen fn` should just keep returning `None` after panicking\"")
}
ResumedAfterDrop(CoroutineKind::Coroutine(_)) => {
write!(f, "\"coroutine resumed after async drop\"")
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
write!(f, "\"`async fn` resumed after async drop\"")
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
write!(f, "\"`async gen fn` resumed after async drop\"")
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
write!(f, "\"`gen fn` resumed after drop\"")
}
}
}
@ -344,6 +366,19 @@ impl<O> AssertKind<O> {
middle_assert_coroutine_resume_after_panic
}
NullPointerDereference => middle_assert_null_ptr_deref,
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
middle_assert_async_resume_after_drop
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
todo!()
}
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
middle_assert_gen_resume_after_drop
}
ResumedAfterDrop(CoroutineKind::Coroutine(_)) => {
middle_assert_coroutine_resume_after_drop
}
MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
}
}
@ -376,7 +411,10 @@ impl<O> AssertKind<O> {
add!("left", format!("{left:#?}"));
add!("right", format!("{right:#?}"));
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {}
ResumedAfterReturn(_)
| ResumedAfterPanic(_)
| NullPointerDereference
| ResumedAfterDrop(_) => {}
MisalignedPointerDereference { required, found } => {
add!("required", format!("{required:#?}"));
add!("found", format!("{found:#?}"));

View File

@ -638,7 +638,7 @@ macro_rules! make_mir_visitor {
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
self.visit_operand(op, location);
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => {
// Nothing to visit
}
MisalignedPointerDereference { required, found } => {

View File

@ -493,6 +493,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
AssertKind::ResumedAfterPanic(coroutine) => {
stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
}
AssertKind::ResumedAfterDrop(coroutine) => {
stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables))
}
AssertKind::MisalignedPointerDereference { required, found } => {
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
required: required.stable(tables),

View File

@ -1464,14 +1464,18 @@ symbols! {
panic_cannot_unwind,
panic_const_add_overflow,
panic_const_async_fn_resumed,
panic_const_async_fn_resumed_drop,
panic_const_async_fn_resumed_panic,
panic_const_async_gen_fn_resumed,
panic_const_async_gen_fn_resumed_drop,
panic_const_async_gen_fn_resumed_panic,
panic_const_coroutine_resumed,
panic_const_coroutine_resumed_drop,
panic_const_coroutine_resumed_panic,
panic_const_div_by_zero,
panic_const_div_overflow,
panic_const_gen_fn_none,
panic_const_gen_fn_none_drop,
panic_const_gen_fn_none_panic,
panic_const_mul_overflow,
panic_const_neg_overflow,

View File

@ -250,6 +250,7 @@ pub enum AssertMessage {
RemainderByZero(Operand),
ResumedAfterReturn(CoroutineKind),
ResumedAfterPanic(CoroutineKind),
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: Operand, found: Operand },
NullPointerDereference,
}
@ -303,6 +304,22 @@ impl AssertMessage {
_,
)) => Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking"),
AssertMessage::ResumedAfterDrop(CoroutineKind::Coroutine(_)) => {
Ok("coroutine resumed after async drop")
}
AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared(
CoroutineDesugaring::Async,
_,
)) => Ok("`async fn` resumed after async drop"),
AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared(
CoroutineDesugaring::Gen,
_,
)) => Ok("`async gen fn` resumed after async drop"),
AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared(
CoroutineDesugaring::AsyncGen,
_,
)) => Ok("`gen fn` should just keep returning `AssertMessage::None` after async drop"),
AssertMessage::BoundsCheck { .. } => Ok("index out of bounds"),
AssertMessage::MisalignedPointerDereference { .. } => {
Ok("misaligned pointer dereference")

View File

@ -301,7 +301,9 @@ fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::R
AssertMessage::NullPointerDereference => {
write!(writer, "\"null pointer dereference occured.\"")
}
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
AssertMessage::ResumedAfterReturn(_)
| AssertMessage::ResumedAfterPanic(_)
| AssertMessage::ResumedAfterDrop(_) => {
write!(writer, "{}", msg.description().unwrap())
}
}

View File

@ -428,8 +428,8 @@ pub trait MirVisitor {
}
AssertMessage::ResumedAfterReturn(_)
| AssertMessage::ResumedAfterPanic(_)
| AssertMessage::NullPointerDereference => {
//nothing to visit
| AssertMessage::NullPointerDereference
| AssertMessage::ResumedAfterDrop(_) => { //nothing to visit
}
AssertMessage::MisalignedPointerDereference { required, found } => {
self.visit_operand(required, location);

View File

@ -155,30 +155,26 @@ pub const fn panic(expr: &'static str) -> ! {
// reducing binary size impact.
macro_rules! panic_const {
($($lang:ident = $message:expr,)+) => {
pub mod panic_const {
use super::*;
$(
/// This is a panic called with a message that's a result of a MIR-produced Assert.
//
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
#[lang = stringify!($lang)]
pub const fn $lang() -> ! {
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
// reduce size overhead. The format_args! macro uses str's Display trait to
// write expr, which calls Formatter::pad, which must accommodate string
// truncation and padding (even though none is used here). Using
// Arguments::new_const may allow the compiler to omit Formatter::pad from the
// output binary, saving up to a few kilobytes.
panic_fmt(fmt::Arguments::new_const(&[$message]));
}
)+
}
$(
/// This is a panic called with a message that's a result of a MIR-produced Assert.
//
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
#[lang = stringify!($lang)]
pub const fn $lang() -> ! {
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
// reduce size overhead. The format_args! macro uses str's Display trait to
// write expr, which calls Formatter::pad, which must accommodate string
// truncation and padding (even though none is used here). Using
// Arguments::new_const may allow the compiler to omit Formatter::pad from the
// output binary, saving up to a few kilobytes.
panic_fmt(fmt::Arguments::new_const(&[$message]));
}
)+
}
}
@ -186,25 +182,37 @@ macro_rules! panic_const {
// slightly different forms. It's not clear if there's a good way to deduplicate without adding
// special cases to the compiler (e.g., a const generic function wouldn't have a single definition
// shared across crates, which is exactly what we want here).
panic_const! {
panic_const_add_overflow = "attempt to add with overflow",
panic_const_sub_overflow = "attempt to subtract with overflow",
panic_const_mul_overflow = "attempt to multiply with overflow",
panic_const_div_overflow = "attempt to divide with overflow",
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
panic_const_neg_overflow = "attempt to negate with overflow",
panic_const_shr_overflow = "attempt to shift right with overflow",
panic_const_shl_overflow = "attempt to shift left with overflow",
panic_const_div_by_zero = "attempt to divide by zero",
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
panic_const_coroutine_resumed = "coroutine resumed after completion",
panic_const_async_fn_resumed = "`async fn` resumed after completion",
panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion",
panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion",
panic_const_coroutine_resumed_panic = "coroutine resumed after panicking",
panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking",
panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking",
panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking",
pub mod panic_const {
use super::*;
panic_const! {
panic_const_add_overflow = "attempt to add with overflow",
panic_const_sub_overflow = "attempt to subtract with overflow",
panic_const_mul_overflow = "attempt to multiply with overflow",
panic_const_div_overflow = "attempt to divide with overflow",
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
panic_const_neg_overflow = "attempt to negate with overflow",
panic_const_shr_overflow = "attempt to shift right with overflow",
panic_const_shl_overflow = "attempt to shift left with overflow",
panic_const_div_by_zero = "attempt to divide by zero",
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
panic_const_coroutine_resumed = "coroutine resumed after completion",
panic_const_async_fn_resumed = "`async fn` resumed after completion",
panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion",
panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion",
panic_const_coroutine_resumed_panic = "coroutine resumed after panicking",
panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking",
panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking",
panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking",
}
// Separated panic constants list for async drop feature
// (May be joined when the corresponding lang items will be in the bootstrap)
#[cfg(not(bootstrap))]
panic_const! {
panic_const_coroutine_resumed_drop = "coroutine resumed after async drop",
panic_const_async_fn_resumed_drop = "`async fn` resumed after async drop",
panic_const_async_gen_fn_resumed_drop = "`async gen fn` resumed after async drop",
panic_const_gen_fn_none_drop = "`gen fn` resumed after async drop",
}
}
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller.