mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Fix Async Drop MIR bug with async_drop_in_place (Squashed)
This commit is contained in:
@@ -326,12 +326,23 @@ fn build_async_drop(
|
||||
const_: Const::zero_sized(pin_obj_new_unchecked_fn),
|
||||
}));
|
||||
|
||||
// Create an intermediate block that does StorageDead(fut) then jumps to succ.
|
||||
// This is necessary because `succ` may differ from `self.succ` (e.g. when
|
||||
// build_async_drop is called from drop_loop, `succ` is the loop header).
|
||||
// Placing StorageDead directly at `self.succ` would miss the loop-back edge,
|
||||
// causing StorageLive(fut) to fire again without a preceding StorageDead.
|
||||
let succ_with_dead = self.new_block_with_statements(
|
||||
unwind,
|
||||
vec![Statement::new(self.source_info, StatementKind::StorageDead(fut.local))],
|
||||
TerminatorKind::Goto { target: succ },
|
||||
);
|
||||
|
||||
// #3:drop_term_bb
|
||||
let drop_term_bb = self.new_block(
|
||||
unwind,
|
||||
TerminatorKind::Drop {
|
||||
place,
|
||||
target: succ,
|
||||
target: succ_with_dead,
|
||||
unwind: unwind.into_action(),
|
||||
replace: false,
|
||||
drop: dropline,
|
||||
@@ -381,12 +392,6 @@ fn build_async_drop(
|
||||
fn_span: self.source_info.span,
|
||||
},
|
||||
);
|
||||
|
||||
// StorageDead(fut) in self.succ block (at the begin)
|
||||
self.elaborator.patch().add_statement(
|
||||
Location { block: self.succ, statement_index: 0 },
|
||||
StatementKind::StorageDead(fut.local),
|
||||
);
|
||||
// StorageDead(fut) in unwind block (at the begin)
|
||||
if let Unwind::To(block) = unwind {
|
||||
self.elaborator.patch().add_statement(
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
|
||||
|
||||
fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: std::future::ResumeTy) -> ()
|
||||
yields ()
|
||||
{
|
||||
let mut _0: ();
|
||||
let mut _3: *mut [Foo; 1];
|
||||
let mut _4: *mut [Foo; 1];
|
||||
let mut _5: *mut [Foo];
|
||||
let mut _6: usize;
|
||||
let mut _7: usize;
|
||||
let mut _8: *mut Foo;
|
||||
let mut _9: bool;
|
||||
let mut _10: *mut Foo;
|
||||
let mut _11: bool;
|
||||
let mut _12: impl std::future::Future<Output = ()>;
|
||||
let mut _13: &mut Foo;
|
||||
let mut _14: std::pin::Pin<&mut Foo>;
|
||||
let mut _15: &mut Foo;
|
||||
let mut _16: *mut Foo;
|
||||
let mut _17: *mut Foo;
|
||||
let mut _18: bool;
|
||||
let mut _19: impl std::future::Future<Output = ()>;
|
||||
let mut _20: &mut Foo;
|
||||
let mut _21: std::pin::Pin<&mut Foo>;
|
||||
let mut _22: &mut Foo;
|
||||
let mut _23: *mut Foo;
|
||||
|
||||
bb0: {
|
||||
_3 = move (_1.0: *mut [Foo; 1]);
|
||||
goto -> bb17;
|
||||
}
|
||||
|
||||
bb1: {
|
||||
return;
|
||||
}
|
||||
|
||||
bb2 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
|
||||
bb3 (cleanup): {
|
||||
_8 = &raw mut (*_5)[_7];
|
||||
_7 = Add(move _7, const 1_usize);
|
||||
drop((*_8)) -> [return: bb4, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb4 (cleanup): {
|
||||
StorageDead(_12);
|
||||
StorageDead(_19);
|
||||
_9 = Eq(copy _7, copy _6);
|
||||
switchInt(move _9) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_10 = &raw mut (*_5)[_7];
|
||||
_7 = Add(move _7, const 1_usize);
|
||||
_13 = &mut (*_10);
|
||||
_14 = Pin::<&mut Foo>::new_unchecked(move _13) -> [return: bb9, unwind: bb4];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_19);
|
||||
_11 = Eq(copy _7, copy _6);
|
||||
switchInt(move _11) -> [0: bb5, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_12);
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
async drop((*_10); poll=_12) -> [return: bb7, unwind: bb4];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
_15 = copy (_14.0: &mut Foo);
|
||||
_16 = &raw mut (*_15);
|
||||
StorageLive(_12);
|
||||
_12 = async_drop_in_place::<Foo>(move _16) -> [return: bb8, unwind: bb4];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_17 = &raw mut (*_5)[_7];
|
||||
_7 = Add(move _7, const 1_usize);
|
||||
_20 = &mut (*_17);
|
||||
_21 = Pin::<&mut Foo>::new_unchecked(move _20) -> [return: bb14, unwind: bb4];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
_18 = Eq(copy _7, copy _6);
|
||||
switchInt(move _18) -> [0: bb10, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb12: {
|
||||
StorageDead(_19);
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb13: {
|
||||
async drop((*_17); poll=_19) -> [return: bb12, unwind: bb4, drop: bb6];
|
||||
}
|
||||
|
||||
bb14: {
|
||||
_22 = copy (_21.0: &mut Foo);
|
||||
_23 = &raw mut (*_22);
|
||||
StorageLive(_19);
|
||||
_19 = async_drop_in_place::<Foo>(move _23) -> [return: bb13, unwind: bb4];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
_6 = PtrMetadata(copy _5);
|
||||
_7 = const 0_usize;
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb16: {
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb17: {
|
||||
_4 = &raw mut (*_3);
|
||||
_5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit));
|
||||
goto -> bb16;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//@edition: 2024
|
||||
//@ test-mir-pass: MentionedItems
|
||||
// skip-filecheck
|
||||
#![feature(async_drop)]
|
||||
#![allow(incomplete_features)]
|
||||
use std::future::AsyncDrop;
|
||||
use std::pin::Pin;
|
||||
struct Foo {
|
||||
my_resource_handle: usize,
|
||||
}
|
||||
impl Foo {
|
||||
fn new(my_resource_handle: usize) -> Self {
|
||||
let out = Foo { my_resource_handle };
|
||||
out
|
||||
}
|
||||
}
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir
|
||||
impl AsyncDrop for Foo {
|
||||
async fn drop(self: Pin<&mut Self>) {}
|
||||
}
|
||||
fn main() {}
|
||||
async fn bar() {
|
||||
[Foo::new(3)];
|
||||
}
|
||||
Reference in New Issue
Block a user