Skip to content

Commit e448c13

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

File tree

24 files changed

+227
-44
lines changed

24 files changed

+227
-44
lines changed

compiler/rustc_borrowck/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,14 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
684684
TerminatorKind::SwitchInt { discr, targets: _ } => {
685685
self.consume_operand(loc, (discr, span), state);
686686
}
687-
TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
687+
TerminatorKind::Drop {
688+
place,
689+
target: _,
690+
unwind: _,
691+
replace,
692+
drop: _,
693+
async_fut: _,
694+
} => {
688695
debug!(
689696
"visit_terminator_drop \
690697
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
@@ -1395,8 +1395,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13951395
}
13961396
}
13971397
TerminatorKind::Unreachable => {}
1398-
TerminatorKind::Drop { target, unwind, .. }
1399-
| TerminatorKind::Assert { target, unwind, .. } => {
1398+
TerminatorKind::Drop { target, unwind, drop, .. } => {
1399+
self.assert_iscleanup(body, block_data, target, is_cleanup);
1400+
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1401+
if let Some(drop) = drop {
1402+
self.assert_iscleanup(body, block_data, drop, is_cleanup);
1403+
}
1404+
}
1405+
TerminatorKind::Assert { target, unwind, .. } => {
14001406
self.assert_iscleanup(body, block_data, target, is_cleanup);
14011407
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
14021408
}

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
@@ -1347,16 +1347,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13471347
MergingSucc::False
13481348
}
13491349

1350-
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
1351-
.codegen_drop_terminator(
1350+
mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
1351+
assert!(
1352+
async_fut.is_none() && drop.is_none(),
1353+
"Async Drop must be expanded or reset to sync before codegen"
1354+
);
1355+
self.codegen_drop_terminator(
13521356
helper,
13531357
bx,
13541358
&terminator.source_info,
13551359
place,
13561360
target,
13571361
unwind,
13581362
mergeable_succ(),
1359-
),
1363+
)
1364+
}
13601365

13611366
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
13621367
.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
@@ -1047,7 +1047,13 @@ impl<'tcx> TerminatorKind<'tcx> {
10471047
Call { target: None, unwind: _, .. } => vec![],
10481048
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
10491049
Yield { drop: None, .. } => vec!["resume".into()],
1050-
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
1050+
Drop { unwind: UnwindAction::Cleanup(_), drop: Some(_), .. } => {
1051+
vec!["return".into(), "unwind".into(), "drop".into()]
1052+
}
1053+
Drop { unwind: UnwindAction::Cleanup(_), drop: None, .. } => {
1054+
vec!["return".into(), "unwind".into()]
1055+
}
1056+
Drop { unwind: _, drop: Some(_), .. } => vec!["return".into(), "drop".into()],
10511057
Drop { unwind: _, .. } => vec!["return".into()],
10521058
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
10531059
vec!["success".into(), "unwind".into()]

compiler/rustc_middle/src/mir/syntax.rs

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

803832
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
804833
/// 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

+8-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,14 @@ macro_rules! make_mir_visitor {
515515
self.visit_operand(discr, location);
516516
}
517517

518-
TerminatorKind::Drop { place, target: _, unwind: _, replace: _ } => {
518+
TerminatorKind::Drop {
519+
place,
520+
target: _,
521+
unwind: _,
522+
replace: _,
523+
drop: _,
524+
async_fut: _,
525+
} => {
519526
self.visit_place(
520527
place,
521528
PlaceContext::MutatingUse(MutatingUseContext::Drop),

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

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

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

+2
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
754754
target: success,
755755
unwind: UnwindAction::Continue,
756756
replace: false,
757+
drop: None,
758+
async_fut: None,
757759
},
758760
);
759761
this.diverge_from(block);

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
}
@@ -845,6 +847,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
845847
target: next,
846848
unwind: UnwindAction::Continue,
847849
replace: false,
850+
drop: None,
851+
async_fut: None,
848852
},
849853
);
850854
block = next;
@@ -1369,6 +1373,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13691373
target: assign,
13701374
unwind: UnwindAction::Cleanup(assign_unwind),
13711375
replace: true,
1376+
drop: None,
1377+
async_fut: None,
13721378
},
13731379
);
13741380
self.diverge_from(block);
@@ -1508,6 +1514,8 @@ fn build_scope_drops<'tcx>(
15081514
target: next,
15091515
unwind: UnwindAction::Continue,
15101516
replace: false,
1517+
drop: None,
1518+
async_fut: None,
15111519
},
15121520
);
15131521
block = next;

0 commit comments

Comments
 (0)