Skip to content

Commit

Permalink
Prereq2 for async drop - ResumedAfterDrop panic messages
Browse files Browse the repository at this point in the history
  • Loading branch information
azhogin committed Sep 7, 2024
1 parent b45015f commit 99b7c82
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 51 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,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)?,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ language_item_table! {
PanicAsyncFnResumedPanic, sym::panic_const_async_fn_resumed_panic, panic_const_async_fn_resumed_panic, Target::Fn, GenericRequirement::None;
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;
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;

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
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
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 =
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ pub enum AssertKind<O> {
RemainderByZero(O),
ResumedAfterReturn(CoroutineKind),
ResumedAfterPanic(CoroutineKind),
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: O, found: O },
}

Expand Down
36 changes: 35 additions & 1 deletion compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,16 @@ impl<O> AssertKind<O> {
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
LangItem::PanicGenFnNonePanic
}
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")
Expand Down Expand Up @@ -284,6 +294,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\"")
}
}
}

Expand Down Expand Up @@ -330,6 +352,18 @@ impl<O> AssertKind<O> {
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => {
middle_assert_coroutine_resume_after_panic
}
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,
}
Expand Down Expand Up @@ -363,7 +397,7 @@ impl<O> AssertKind<O> {
add!("left", format!("{left:#?}"));
add!("right", format!("{right:#?}"));
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
ResumedAfterReturn(_) | ResumedAfterPanic(_) | ResumedAfterDrop(_) => {}
MisalignedPointerDereference { required, found } => {
add!("required", format!("{required:#?}"));
add!("found", format!("{found:#?}"));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ macro_rules! make_mir_visitor {
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
self.visit_operand(op, location);
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
ResumedAfterReturn(_) | ResumedAfterPanic(_) | ResumedAfterDrop(_) => {
// Nothing to visit
}
MisalignedPointerDereference { required, found } => {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,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),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,14 +1370,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,
Expand Down
17 changes: 17 additions & 0 deletions compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ pub enum AssertMessage {
RemainderByZero(Operand),
ResumedAfterReturn(CoroutineKind),
ResumedAfterPanic(CoroutineKind),
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: Operand, found: Operand },
}

Expand Down Expand Up @@ -302,6 +303,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")
Expand Down
4 changes: 3 additions & 1 deletion compiler/stable_mir/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,9 @@ fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::R
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}"
)
}
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
AssertMessage::ResumedAfterReturn(_)
| AssertMessage::ResumedAfterPanic(_)
| AssertMessage::ResumedAfterDrop(_) => {
write!(writer, "{}", msg.description().unwrap())
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/stable_mir/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,9 @@ pub trait MirVisitor {
| AssertMessage::RemainderByZero(op) => {
self.visit_operand(op, location);
}
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => { //nothing to visit
AssertMessage::ResumedAfterReturn(_)
| AssertMessage::ResumedAfterPanic(_)
| AssertMessage::ResumedAfterDrop(_) => { //nothing to visit
}
AssertMessage::MisalignedPointerDereference { required, found } => {
self.visit_operand(required, location);
Expand Down
102 changes: 55 additions & 47 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,56 +158,64 @@ 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_unstable(feature = "panic_internals", issue = "none")]
#[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_unstable(feature = "panic_internals", issue = "none")]
#[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]));
}
)+
}
}

// Unfortunately this set of strings is replicated here and in a few places in the compiler in
// 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::*;
// Unfortunately this set of strings is replicated here and in a few places in the compiler in
// 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",
}
// 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.
Expand Down

0 comments on commit 99b7c82

Please sign in to comment.