Skip to content

Subpart7 for async drop (major1) - library changes #129742

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
@@ -659,7 +659,14 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(loc, (discr, span), state);
}
TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
TerminatorKind::Drop {
place,
target: _,
unwind: _,
replace,
drop: _,
async_fut: _,
} => {
debug!(
"visit_terminator_drop \
loc: {:?} term: {:?} place: {:?} span: {:?}",
Original file line number Diff line number Diff line change
@@ -101,7 +101,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(location, discr);
}
TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace } => {
TerminatorKind::Drop {
place: drop_place,
target: _,
unwind: _,
replace,
drop: _,
async_fut: _,
} => {
let write_kind =
if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
self.access_place(
10 changes: 8 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -2086,8 +2086,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
TerminatorKind::Unreachable => {}
TerminatorKind::Drop { target, unwind, .. }
| TerminatorKind::Assert { target, unwind, .. } => {
TerminatorKind::Drop { target, unwind, drop, .. } => {
self.assert_iscleanup(block_data, target, is_cleanup);
self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
if let Some(drop) = drop {
self.assert_iscleanup(block_data, drop, is_cleanup);
}
}
TerminatorKind::Assert { target, unwind, .. } => {
self.assert_iscleanup(block_data, target, is_cleanup);
self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
}
9 changes: 5 additions & 4 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
@@ -441,7 +441,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
Err(instance) => Some(instance),
}
}
InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => {
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
// it is `func returning noop future`
InstanceKind::DropGlue(_, None) => {
// empty drop glue - a nop.
let dest = target.expect("Non terminating drop_in_place_real???");
let ret_block = fx.get_block(dest);
@@ -707,9 +709,8 @@ pub(crate) fn codegen_drop<'tcx>(
let ty = drop_place.layout().ty;
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty);

if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) =
drop_instance.def
{
// AsyncDropGlueCtorShim can't be here
if let ty::InstanceKind::DropGlue(_, None) = drop_instance.def {
// we don't actually need to drop anything
} else {
match ty.kind() {
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
@@ -565,7 +565,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
| TerminatorKind::CoroutineDrop => {
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
}
TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
TerminatorKind::Drop { place, target, unwind: _, replace: _, drop, async_fut } => {
assert!(
async_fut.is_none() && drop.is_none(),
"Async Drop must be expanded or reset to sync before codegen"
);
let drop_place = codegen_place(fx, *place);
crate::abi::codegen_drop(fx, source_info, drop_place, *target);
}
Original file line number Diff line number Diff line change
@@ -721,8 +721,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
_ => unreachable!(),
};

let coroutine_layout =
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();

let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
Original file line number Diff line number Diff line change
@@ -174,10 +174,8 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
DIFlags::FlagZero,
),
|cx, coroutine_type_di_node| {
let coroutine_layout = cx
.tcx
.coroutine_layout(coroutine_def_id, coroutine_args.as_coroutine().kind_ty())
.unwrap();
let coroutine_layout =
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args).unwrap();

let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
coroutine_type_and_layout.variants
30 changes: 27 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
@@ -374,7 +374,7 @@ fn exported_symbols_provider_local(
));
}
MonoItem::Fn(Instance {
def: InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)),
def: InstanceKind::AsyncDropGlueCtorShim(_, ty),
args,
}) => {
// A little sanity-check
@@ -388,6 +388,16 @@ fn exported_symbols_provider_local(
},
));
}
MonoItem::Fn(Instance { def: InstanceKind::AsyncDropGlue(_, ty), args: _ }) => {
symbols.push((
ExportedSymbol::AsyncDropGlue(ty),
SymbolExportInfo {
level: SymbolExportLevel::Rust,
kind: SymbolExportKind::Text,
used: false,
},
));
}
_ => {
// Any other symbols don't qualify for sharing
}
@@ -411,6 +421,7 @@ fn upstream_monomorphizations_provider(

let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
let async_drop_in_place_poll_fn_def_id = tcx.lang_items().async_drop_in_place_poll_fn();

for &cnum in cnums.iter() {
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
@@ -429,8 +440,13 @@ fn upstream_monomorphizations_provider(
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
(async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
} else {
// `drop_in_place` in place does not exist, don't try
// to use it.
continue;
}
}
ExportedSymbol::AsyncDropGlue(ty) => {
if let Some(poll_fn_def_id) = async_drop_in_place_poll_fn_def_id {
(poll_fn_def_id, tcx.mk_args(&[ty.into()]))
} else {
continue;
}
}
@@ -582,6 +598,13 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
instantiating_crate,
)
}
ExportedSymbol::AsyncDropGlue(ty) => {
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
tcx,
Instance::resolve_async_drop_in_place_poll(tcx, ty),
instantiating_crate,
)
}
ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
}
}
@@ -604,6 +627,7 @@ fn calling_convention_for_symbol<'tcx>(
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
// target's default symbol decoration scheme.
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
ExportedSymbol::AsyncDropGlue(..) => None,
// NoDefId always follow the target's default symbol decoration scheme.
ExportedSymbol::NoDefId(..) => None,
// ThreadLocalShim always follow the target's default symbol decoration scheme.
18 changes: 11 additions & 7 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
@@ -926,10 +926,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

let def = instance.map(|i| i.def);

if let Some(
ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None),
) = def
{
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
// it is `func returning noop future`
if let Some(ty::InstanceKind::DropGlue(_, None)) = def {
// Empty drop glue; a no-op.
let target = target.unwrap();
return helper.funclet_br(self, bx, target, mergeable_succ);
@@ -1386,16 +1385,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
MergingSucc::False
}

mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
.codegen_drop_terminator(
mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
assert!(
async_fut.is_none() && drop.is_none(),
"Async Drop must be expanded or reset to sync before codegen"
);
self.codegen_drop_terminator(
helper,
bx,
&terminator.source_info,
place,
target,
unwind,
mergeable_succ(),
),
)
}

mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
.codegen_assert_terminator(
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
@@ -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 { required, found } => MisalignedPointerDereference {
required: eval_to_int(required)?,
found: eval_to_int(found)?,
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
@@ -570,6 +570,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
| ty::InstanceKind::FnPtrAddrShim(..)
| ty::InstanceKind::ThreadLocalShim(..)
| ty::InstanceKind::AsyncDropGlueCtorShim(..)
| ty::InstanceKind::AsyncDropGlue(..)
| ty::InstanceKind::FutureDropPollShim(..)
| ty::InstanceKind::Item(_) => {
// We need MIR for this fn.
// Note that this can be an intrinsic, if we are executing its fallback body.
6 changes: 5 additions & 1 deletion compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
@@ -539,7 +539,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}

Drop { place, target, unwind, replace: _ } => {
Drop { place, target, unwind, replace: _, drop, async_fut } => {
assert!(
async_fut.is_none() && drop.is_none(),
"Async Drop must be expanded or reset to sync in runtime MIR"
);
let place = self.eval_place(place)?;
let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
if let ty::InstanceKind::DropGlue(_, None) = instance.def {
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
@@ -381,6 +381,8 @@ declare_features! (
(unstable, associated_const_equality, "1.58.0", Some(92827)),
/// Allows associated type defaults.
(unstable, associated_type_defaults, "1.2.0", Some(29661)),
/// Allows implementing `AsyncDrop`.
(incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)),
Comment on lines +384 to +385
Copy link
Member

@workingjubilee workingjubilee Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see feature gates in the compiler being tested. If this all hinges on the library feature gate, then let it hinge on the library feature gate, and remove the compiler gate.

Suggested change
/// Allows implementing `AsyncDrop`.
(incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)),

/// Allows async functions to be called from `dyn Trait`.
(incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)),
/// Allows `#[track_caller]` on async functions.
20 changes: 7 additions & 13 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -188,19 +188,10 @@ language_item_table! {

Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;

AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::Exact(0);
AsyncDestruct, sym::async_destruct, async_destruct_trait, Target::Trait, GenericRequirement::Exact(0);
AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::None;
AsyncDropInPlace, sym::async_drop_in_place, async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
SurfaceAsyncDropInPlace, sym::surface_async_drop_in_place, surface_async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropSurfaceDropInPlace, sym::async_drop_surface_drop_in_place, async_drop_surface_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropSlice, sym::async_drop_slice, async_drop_slice_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropChain, sym::async_drop_chain, async_drop_chain_fn, Target::Fn, GenericRequirement::Exact(2);
AsyncDropNoop, sym::async_drop_noop, async_drop_noop_fn, Target::Fn, GenericRequirement::Exact(0);
AsyncDropDeferredDropInPlace, sym::async_drop_deferred_drop_in_place, async_drop_deferred_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropFuse, sym::async_drop_fuse, async_drop_fuse_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropDefer, sym::async_drop_defer, async_drop_defer_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropEither, sym::async_drop_either, async_drop_either_fn, Target::Fn, GenericRequirement::Exact(3);
AsyncDropInPlacePoll, sym::async_drop_in_place_poll, async_drop_in_place_poll_fn, Target::Closure, GenericRequirement::Exact(1);
FutureDropPoll, sym::future_drop_poll, future_drop_poll_fn, Target::Fn, GenericRequirement::Exact(1);

CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
@@ -318,6 +309,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;

@@ -330,7 +325,6 @@ language_item_table! {

ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
FallbackSurfaceDrop, sym::fallback_surface_drop, fallback_surface_drop_fn, Target::Fn, GenericRequirement::None;
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;

/// For all binary crates without `#![no_main]`, Rust will generate a "main" function.
6 changes: 2 additions & 4 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
@@ -34,11 +34,9 @@ pub(crate) fn check_legal_trait_for_method_call(
receiver: Option<Span>,
expr_span: Span,
trait_id: DefId,
body_id: DefId,
_body_id: DefId,
) -> Result<(), ErrorGuaranteed> {
if tcx.is_lang_item(trait_id, LangItem::Drop)
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
{
if tcx.is_lang_item(trait_id, LangItem::Drop) {
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
errors::ExplicitDestructorCallSugg::Snippet {
lo: expr_span.shrink_to_lo(),
12 changes: 7 additions & 5 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
@@ -979,11 +979,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
let _ = tcx.ensure_ok().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
);
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
if !tcx.is_templated_coroutine(def_id.to_def_id()) {
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
}
}
});
});
6 changes: 6 additions & 0 deletions compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
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 =
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/arena.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ macro_rules! arena_types {
($macro:path) => (
$macro!([
[] layout: rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx>,
[] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>,
[] fn_abi: rustc_target::callconv::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDefData,
Loading