Skip to content

Commit e8f28c1

Browse files
committed
Prereq1 for async drop - added drop & async_fut Option fields in Drop terminator
1 parent d2f335d commit e8f28c1

File tree

24 files changed

+221
-43
lines changed

24 files changed

+221
-43
lines changed

compiler/rustc_borrowck/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,14 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
685685
TerminatorKind::SwitchInt { discr, targets: _ } => {
686686
self.consume_operand(loc, (discr, span), state);
687687
}
688-
TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
688+
TerminatorKind::Drop {
689+
place,
690+
target: _,
691+
unwind: _,
692+
replace,
693+
drop: _,
694+
async_fut: _,
695+
} => {
689696
debug!(
690697
"visit_terminator_drop \
691698
loc: {:?} term: {:?} place: {:?} span: {:?}",

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
101101
TerminatorKind::SwitchInt { discr, targets: _ } => {
102102
self.consume_operand(location, discr);
103103
}
104-
TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace } => {
104+
TerminatorKind::Drop {
105+
place: drop_place,
106+
target: _,
107+
unwind: _,
108+
replace,
109+
drop: _,
110+
async_fut: _,
111+
} => {
105112
let write_kind =
106113
if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
107114
self.access_place(

compiler/rustc_borrowck/src/type_check/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1396,8 +1396,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13961396
}
13971397
}
13981398
TerminatorKind::Unreachable => {}
1399-
TerminatorKind::Drop { target, unwind, .. }
1400-
| TerminatorKind::Assert { target, unwind, .. } => {
1399+
TerminatorKind::Drop { target, unwind, drop, .. } => {
1400+
self.assert_iscleanup(body, block_data, target, is_cleanup);
1401+
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1402+
if let Some(drop) = drop {
1403+
self.assert_iscleanup(body, block_data, drop, is_cleanup);
1404+
}
1405+
}
1406+
TerminatorKind::Assert { target, unwind, .. } => {
14011407
self.assert_iscleanup(body, block_data, target, is_cleanup);
14021408
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
14031409
}

compiler/rustc_codegen_cranelift/src/base.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
565565
| TerminatorKind::CoroutineDrop => {
566566
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
567567
}
568-
TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
568+
TerminatorKind::Drop { place, target, unwind: _, replace: _, drop, async_fut } => {
569+
assert!(
570+
async_fut.is_none() && drop.is_none(),
571+
"Async Drop must be expanded or reset to sync before codegen"
572+
);
569573
let drop_place = codegen_place(fx, *place);
570574
crate::abi::codegen_drop(fx, source_info, drop_place, *target);
571575
}

compiler/rustc_codegen_ssa/src/mir/block.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1334,16 +1334,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13341334
MergingSucc::False
13351335
}
13361336

1337-
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
1338-
.codegen_drop_terminator(
1337+
mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
1338+
assert!(
1339+
async_fut.is_none() && drop.is_none(),
1340+
"Async Drop must be expanded or reset to sync before codegen"
1341+
);
1342+
self.codegen_drop_terminator(
13391343
helper,
13401344
bx,
13411345
&terminator.source_info,
13421346
place,
13431347
target,
13441348
unwind,
13451349
mergeable_succ(),
1346-
),
1350+
)
1351+
}
13471352

13481353
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
13491354
.codegen_assert_terminator(

compiler/rustc_const_eval/src/interpret/step.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
539539
}
540540
}
541541

542-
Drop { place, target, unwind, replace: _ } => {
542+
Drop { place, target, unwind, replace: _, drop, async_fut } => {
543+
assert!(
544+
async_fut.is_none() && drop.is_none(),
545+
"Async Drop must be expanded or reset to sync in runtime MIR"
546+
);
543547
let place = self.eval_place(place)?;
544548
let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
545549
if let ty::InstanceKind::DropGlue(_, None) = instance.def {

compiler/rustc_middle/src/mir/pretty.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,13 @@ impl<'tcx> TerminatorKind<'tcx> {
10511051
Call { target: None, unwind: _, .. } => vec![],
10521052
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
10531053
Yield { drop: None, .. } => vec!["resume".into()],
1054-
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
1054+
Drop { unwind: UnwindAction::Cleanup(_), drop: Some(_), .. } => {
1055+
vec!["return".into(), "unwind".into(), "drop".into()]
1056+
}
1057+
Drop { unwind: UnwindAction::Cleanup(_), drop: None, .. } => {
1058+
vec!["return".into(), "unwind".into()]
1059+
}
1060+
Drop { unwind: _, drop: Some(_), .. } => vec!["return".into(), "drop".into()],
10551061
Drop { unwind: _, .. } => vec!["return".into()],
10561062
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
10571063
vec!["success".into(), "unwind".into()]

compiler/rustc_middle/src/mir/syntax.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub enum MirPhase {
7171
/// is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be misaligned
7272
/// for this reason implicitly moves `P` to a temporary before dropping. Runtime MIR has no such
7373
/// rules, and dropping a misaligned place is simply UB.
74+
/// - Async drops: after drop elaboration some drops may become async (`drop`, `async_fut` fields).
75+
/// StateTransform pass will expand those async drops or reset to sync.
7476
/// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In runtime
7577
/// MIR, this is UB.
7678
/// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way
@@ -788,7 +790,34 @@ pub enum TerminatorKind<'tcx> {
788790
/// The `replace` flag indicates whether this terminator was created as part of an assignment.
789791
/// This should only be used for diagnostic purposes, and does not have any operational
790792
/// meaning.
791-
Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
793+
///
794+
/// Async drop processing:
795+
/// In compiler/rustc_mir_build/src/build/scope.rs we detect possible async drop:
796+
/// drop of object with `needs_async_drop`.
797+
/// Async drop later, in StateTransform pass, may be expanded into additional yield-point
798+
/// for poll-loop of async drop future.
799+
/// So we need prepared 'drop' target block in the similar way as for `Yield` terminator
800+
/// (see `drops.build_mir::<CoroutineDrop>` in scopes.rs).
801+
/// In compiler/rustc_mir_transform/src/elaborate_drops.rs for object implementing `AsyncDrop` trait
802+
/// we need to prepare async drop feature - resolve `AsyncDrop::drop` and codegen call.
803+
/// `async_fut` is set to the corresponding local.
804+
/// For coroutine drop we don't need this logic because coroutine drop works with the same
805+
/// layout object as coroutine itself. So `async_fut` will be `None` for coroutine drop.
806+
/// Both `drop` and `async_fut` fields are only used in compiler/rustc_mir_transform/src/coroutine.rs,
807+
/// StateTransform pass. In `expand_async_drops` async drops are expanded
808+
/// into one or two yield points with poll ready/pending switch.
809+
/// When a coroutine has any internal async drop, the coroutine drop function will be async
810+
/// (generated by `create_coroutine_drop_shim_async`, not `create_coroutine_drop_shim`).
811+
Drop {
812+
place: Place<'tcx>,
813+
target: BasicBlock,
814+
unwind: UnwindAction,
815+
replace: bool,
816+
/// Cleanup to be done if the coroutine is dropped at this suspend point (for async drop).
817+
drop: Option<BasicBlock>,
818+
/// Prepared async future local (for async drop)
819+
async_fut: Option<Local>,
820+
},
792821

793822
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
794823
/// the referred to function. The operand types must match the argument types of the function.

compiler/rustc_middle/src/mir/terminator.rs

+67-19
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ mod helper {
433433
#[inline]
434434
pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
435435
let target = self.target_for_value(value);
436-
(&[]).into_iter().copied().chain(Some(target))
436+
(&[]).into_iter().copied().chain(Some(target).into_iter().chain(None))
437437
}
438438
}
439439

@@ -442,77 +442,123 @@ mod helper {
442442
pub fn successors(&self) -> Successors<'_> {
443443
use self::TerminatorKind::*;
444444
match *self {
445+
// 3-successors for async drop: target, unwind, dropline (parent coroutine drop)
446+
Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: Some(d), .. } => {
447+
slice::from_ref(t)
448+
.into_iter()
449+
.copied()
450+
.chain(Some(u).into_iter().chain(Some(d)))
451+
}
452+
// 2-successors
445453
Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. }
446454
| Yield { resume: ref t, drop: Some(u), .. }
447-
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
455+
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: None, .. }
456+
| Drop { target: ref t, unwind: _, drop: Some(u), .. }
448457
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
449458
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
450-
slice::from_ref(t).into_iter().copied().chain(Some(u))
459+
slice::from_ref(t).into_iter().copied().chain(Some(u).into_iter().chain(None))
451460
}
461+
// single successor
452462
Goto { target: ref t }
453463
| Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. }
454464
| Call { target: Some(ref t), unwind: _, .. }
455465
| Yield { resume: ref t, drop: None, .. }
456466
| Drop { target: ref t, unwind: _, .. }
457467
| Assert { target: ref t, unwind: _, .. }
458468
| FalseUnwind { real_target: ref t, unwind: _ } => {
459-
slice::from_ref(t).into_iter().copied().chain(None)
469+
slice::from_ref(t).into_iter().copied().chain(None.into_iter().chain(None))
460470
}
471+
// No successors
461472
UnwindResume
462473
| UnwindTerminate(_)
463474
| CoroutineDrop
464475
| Return
465476
| Unreachable
466477
| TailCall { .. }
467-
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
478+
| Call { target: None, unwind: _, .. } => {
479+
(&[]).into_iter().copied().chain(None.into_iter().chain(None))
480+
}
481+
// Multiple successors
468482
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
469-
targets.iter().copied().chain(Some(u))
483+
targets.iter().copied().chain(Some(u).into_iter().chain(None))
484+
}
485+
InlineAsm { ref targets, unwind: _, .. } => {
486+
targets.iter().copied().chain(None.into_iter().chain(None))
470487
}
471-
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
472-
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
473-
FalseEdge { ref real_target, imaginary_target } => {
474-
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
488+
SwitchInt { ref targets, .. } => {
489+
targets.targets.iter().copied().chain(None.into_iter().chain(None))
475490
}
491+
// FalseEdge
492+
FalseEdge { ref real_target, imaginary_target } => slice::from_ref(real_target)
493+
.into_iter()
494+
.copied()
495+
.chain(Some(imaginary_target).into_iter().chain(None)),
476496
}
477497
}
478498

479499
#[inline]
480500
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
481501
use self::TerminatorKind::*;
482502
match *self {
503+
// 3-successors for async drop: target, unwind, dropline (parent coroutine drop)
504+
Drop {
505+
target: ref mut t,
506+
unwind: UnwindAction::Cleanup(ref mut u),
507+
drop: Some(ref mut d),
508+
..
509+
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(Some(d))),
510+
// 2-successors
483511
Call {
484512
target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), ..
485513
}
486514
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
487-
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
515+
| Drop {
516+
target: ref mut t,
517+
unwind: UnwindAction::Cleanup(ref mut u),
518+
drop: None,
519+
..
520+
}
521+
| Drop { target: ref mut t, unwind: _, drop: Some(ref mut u), .. }
488522
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
489523
| FalseUnwind {
490524
real_target: ref mut t,
491525
unwind: UnwindAction::Cleanup(ref mut u),
492-
} => slice::from_mut(t).into_iter().chain(Some(u)),
526+
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(None)),
527+
// single successor
493528
Goto { target: ref mut t }
494529
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
495530
| Call { target: Some(ref mut t), unwind: _, .. }
496531
| Yield { resume: ref mut t, drop: None, .. }
497532
| Drop { target: ref mut t, unwind: _, .. }
498533
| Assert { target: ref mut t, unwind: _, .. }
499534
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
500-
slice::from_mut(t).into_iter().chain(None)
535+
slice::from_mut(t).into_iter().chain(None.into_iter().chain(None))
501536
}
537+
// No successors
502538
UnwindResume
503539
| UnwindTerminate(_)
504540
| CoroutineDrop
505541
| Return
506542
| Unreachable
507543
| TailCall { .. }
508-
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
544+
| Call { target: None, unwind: _, .. } => {
545+
(&mut []).into_iter().chain(None.into_iter().chain(None))
546+
}
547+
// Multiple successors
509548
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
510-
targets.iter_mut().chain(Some(u))
549+
targets.iter_mut().chain(Some(u).into_iter().chain(None))
550+
}
551+
InlineAsm { ref mut targets, unwind: _, .. } => {
552+
targets.iter_mut().chain(None.into_iter().chain(None))
553+
}
554+
SwitchInt { ref mut targets, .. } => {
555+
targets.targets.iter_mut().chain(None.into_iter().chain(None))
511556
}
512-
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
513-
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
557+
// FalseEdge
514558
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
515-
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
559+
slice::from_mut(real_target)
560+
.into_iter()
561+
.chain(Some(imaginary_target).into_iter().chain(None))
516562
}
517563
}
518564
}
@@ -645,8 +691,10 @@ impl<'tcx> TerminatorKind<'tcx> {
645691

646692
Goto { target } => TerminatorEdges::Single(target),
647693

694+
// FIXME: Maybe we need also TerminatorEdges::Trio for async drop
695+
// (target + unwind + dropline)
648696
Assert { target, unwind, expected: _, msg: _, cond: _ }
649-
| Drop { target, unwind, place: _, replace: _ }
697+
| Drop { target, unwind, place: _, replace: _, drop: _, async_fut: _ }
650698
| FalseUnwind { real_target: target, unwind } => match unwind {
651699
UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
652700
UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => {

compiler/rustc_middle/src/mir/visit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ macro_rules! make_mir_visitor {
512512
target: _,
513513
unwind: _,
514514
replace: _,
515+
drop: _,
516+
async_fut: _,
515517
} => {
516518
self.visit_place(
517519
place,

compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
7070
target: self.parse_return_to(args[1])?,
7171
unwind: self.parse_unwind_action(args[2])?,
7272
replace: false,
73+
drop: None,
74+
async_fut: None,
7375
})
7476
},
7577
@call(mir_call, args) => {

compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs

+2
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
744744
target: success,
745745
unwind: UnwindAction::Continue,
746746
replace: false,
747+
drop: None,
748+
async_fut: None,
747749
});
748750
this.diverge_from(block);
749751
block = success;

compiler/rustc_mir_build/src/builder/scope.rs

+8
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ impl DropTree {
402402
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
403403
place: drop_node.data.local.into(),
404404
replace: false,
405+
drop: None,
406+
async_fut: None,
405407
};
406408
cfg.terminate(block, drop_node.data.source_info, terminator);
407409
}
@@ -838,6 +840,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
838840
target: next,
839841
unwind: UnwindAction::Continue,
840842
replace: false,
843+
drop: None,
844+
async_fut: None,
841845
});
842846
block = next;
843847
}
@@ -1355,6 +1359,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13551359
target: assign,
13561360
unwind: UnwindAction::Cleanup(assign_unwind),
13571361
replace: true,
1362+
drop: None,
1363+
async_fut: None,
13581364
});
13591365
self.diverge_from(block);
13601366

@@ -1486,6 +1492,8 @@ fn build_scope_drops<'tcx>(
14861492
target: next,
14871493
unwind: UnwindAction::Continue,
14881494
replace: false,
1495+
drop: None,
1496+
async_fut: None,
14891497
});
14901498
block = next;
14911499
}

0 commit comments

Comments
 (0)