Skip to content

Commit 09344ae

Browse files
committed
Prereq1 for async drop - added drop & async_fut Option fields in Drop terminator
1 parent 45b40a7 commit 09344ae

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
@@ -2086,8 +2086,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20862086
}
20872087
}
20882088
TerminatorKind::Unreachable => {}
2089-
TerminatorKind::Drop { target, unwind, .. }
2090-
| TerminatorKind::Assert { target, unwind, .. } => {
2089+
TerminatorKind::Drop { target, unwind, drop, .. } => {
2090+
self.assert_iscleanup(body, block_data, target, is_cleanup);
2091+
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
2092+
if let Some(drop) = drop {
2093+
self.assert_iscleanup(body, block_data, drop, is_cleanup);
2094+
}
2095+
}
2096+
TerminatorKind::Assert { target, unwind, .. } => {
20912097
self.assert_iscleanup(block_data, target, is_cleanup);
20922098
self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
20932099
}

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
@@ -1386,16 +1386,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13861386
MergingSucc::False
13871387
}
13881388

1389-
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
1390-
.codegen_drop_terminator(
1389+
mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
1390+
assert!(
1391+
async_fut.is_none() && drop.is_none(),
1392+
"Async Drop must be expanded or reset to sync before codegen"
1393+
);
1394+
self.codegen_drop_terminator(
13911395
helper,
13921396
bx,
13931397
&terminator.source_info,
13941398
place,
13951399
target,
13961400
unwind,
13971401
mergeable_succ(),
1398-
),
1402+
)
1403+
}
13991404

14001405
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
14011406
.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
@@ -1050,7 +1050,13 @@ impl<'tcx> TerminatorKind<'tcx> {
10501050
Call { target: None, unwind: _, .. } => vec![],
10511051
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
10521052
Yield { drop: None, .. } => vec!["resume".into()],
1053-
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
1053+
Drop { unwind: UnwindAction::Cleanup(_), drop: Some(_), .. } => {
1054+
vec!["return".into(), "unwind".into(), "drop".into()]
1055+
}
1056+
Drop { unwind: UnwindAction::Cleanup(_), drop: None, .. } => {
1057+
vec!["return".into(), "unwind".into()]
1058+
}
1059+
Drop { unwind: _, drop: Some(_), .. } => vec!["return".into(), "drop".into()],
10541060
Drop { unwind: _, .. } => vec!["return".into()],
10551061
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
10561062
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
@@ -710,7 +712,34 @@ pub enum TerminatorKind<'tcx> {
710712
/// The `replace` flag indicates whether this terminator was created as part of an assignment.
711713
/// This should only be used for diagnostic purposes, and does not have any operational
712714
/// meaning.
713-
Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
715+
///
716+
/// Async drop processing:
717+
/// In compiler/rustc_mir_build/src/build/scope.rs we detect possible async drop:
718+
/// drop of object with `needs_async_drop`.
719+
/// Async drop later, in StateTransform pass, may be expanded into additional yield-point
720+
/// for poll-loop of async drop future.
721+
/// So we need prepared 'drop' target block in the similar way as for `Yield` terminator
722+
/// (see `drops.build_mir::<CoroutineDrop>` in scopes.rs).
723+
/// In compiler/rustc_mir_transform/src/elaborate_drops.rs for object implementing `AsyncDrop` trait
724+
/// we need to prepare async drop feature - resolve `AsyncDrop::drop` and codegen call.
725+
/// `async_fut` is set to the corresponding local.
726+
/// For coroutine drop we don't need this logic because coroutine drop works with the same
727+
/// layout object as coroutine itself. So `async_fut` will be `None` for coroutine drop.
728+
/// Both `drop` and `async_fut` fields are only used in compiler/rustc_mir_transform/src/coroutine.rs,
729+
/// StateTransform pass. In `expand_async_drops` async drops are expanded
730+
/// into one or two yield points with poll ready/pending switch.
731+
/// When a coroutine has any internal async drop, the coroutine drop function will be async
732+
/// (generated by `create_coroutine_drop_shim_async`, not `create_coroutine_drop_shim`).
733+
Drop {
734+
place: Place<'tcx>,
735+
target: BasicBlock,
736+
unwind: UnwindAction,
737+
replace: bool,
738+
/// Cleanup to be done if the coroutine is dropped at this suspend point (for async drop).
739+
drop: Option<BasicBlock>,
740+
/// Prepared async future local (for async drop)
741+
async_fut: Option<Local>,
742+
},
714743

715744
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
716745
/// 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
@@ -457,7 +457,7 @@ mod helper {
457457
#[cfg_attr(not(bootstrap), define_opaque(Successors))]
458458
pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
459459
let target = self.target_for_value(value);
460-
(&[]).into_iter().copied().chain(Some(target))
460+
(&[]).into_iter().copied().chain(Some(target).into_iter().chain(None))
461461
}
462462
}
463463

@@ -467,37 +467,57 @@ mod helper {
467467
pub fn successors(&self) -> Successors<'_> {
468468
use self::TerminatorKind::*;
469469
match *self {
470+
// 3-successors for async drop: target, unwind, dropline (parent coroutine drop)
471+
Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: Some(d), .. } => {
472+
slice::from_ref(t)
473+
.into_iter()
474+
.copied()
475+
.chain(Some(u).into_iter().chain(Some(d)))
476+
}
477+
// 2-successors
470478
Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. }
471479
| Yield { resume: ref t, drop: Some(u), .. }
472-
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
480+
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: None, .. }
481+
| Drop { target: ref t, unwind: _, drop: Some(u), .. }
473482
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
474483
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
475-
slice::from_ref(t).into_iter().copied().chain(Some(u))
484+
slice::from_ref(t).into_iter().copied().chain(Some(u).into_iter().chain(None))
476485
}
486+
// single successor
477487
Goto { target: ref t }
478488
| Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. }
479489
| Call { target: Some(ref t), unwind: _, .. }
480490
| Yield { resume: ref t, drop: None, .. }
481491
| Drop { target: ref t, unwind: _, .. }
482492
| Assert { target: ref t, unwind: _, .. }
483493
| FalseUnwind { real_target: ref t, unwind: _ } => {
484-
slice::from_ref(t).into_iter().copied().chain(None)
494+
slice::from_ref(t).into_iter().copied().chain(None.into_iter().chain(None))
485495
}
496+
// No successors
486497
UnwindResume
487498
| UnwindTerminate(_)
488499
| CoroutineDrop
489500
| Return
490501
| Unreachable
491502
| TailCall { .. }
492-
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
503+
| Call { target: None, unwind: _, .. } => {
504+
(&[]).into_iter().copied().chain(None.into_iter().chain(None))
505+
}
506+
// Multiple successors
493507
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
494-
targets.iter().copied().chain(Some(u))
508+
targets.iter().copied().chain(Some(u).into_iter().chain(None))
509+
}
510+
InlineAsm { ref targets, unwind: _, .. } => {
511+
targets.iter().copied().chain(None.into_iter().chain(None))
495512
}
496-
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
497-
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
498-
FalseEdge { ref real_target, imaginary_target } => {
499-
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
513+
SwitchInt { ref targets, .. } => {
514+
targets.targets.iter().copied().chain(None.into_iter().chain(None))
500515
}
516+
// FalseEdge
517+
FalseEdge { ref real_target, imaginary_target } => slice::from_ref(real_target)
518+
.into_iter()
519+
.copied()
520+
.chain(Some(imaginary_target).into_iter().chain(None)),
501521
}
502522
}
503523

@@ -506,39 +526,65 @@ mod helper {
506526
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
507527
use self::TerminatorKind::*;
508528
match *self {
529+
// 3-successors for async drop: target, unwind, dropline (parent coroutine drop)
530+
Drop {
531+
target: ref mut t,
532+
unwind: UnwindAction::Cleanup(ref mut u),
533+
drop: Some(ref mut d),
534+
..
535+
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(Some(d))),
536+
// 2-successors
509537
Call {
510538
target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), ..
511539
}
512540
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
513-
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
541+
| Drop {
542+
target: ref mut t,
543+
unwind: UnwindAction::Cleanup(ref mut u),
544+
drop: None,
545+
..
546+
}
547+
| Drop { target: ref mut t, unwind: _, drop: Some(ref mut u), .. }
514548
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
515549
| FalseUnwind {
516550
real_target: ref mut t,
517551
unwind: UnwindAction::Cleanup(ref mut u),
518-
} => slice::from_mut(t).into_iter().chain(Some(u)),
552+
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(None)),
553+
// single successor
519554
Goto { target: ref mut t }
520555
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
521556
| Call { target: Some(ref mut t), unwind: _, .. }
522557
| Yield { resume: ref mut t, drop: None, .. }
523558
| Drop { target: ref mut t, unwind: _, .. }
524559
| Assert { target: ref mut t, unwind: _, .. }
525560
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
526-
slice::from_mut(t).into_iter().chain(None)
561+
slice::from_mut(t).into_iter().chain(None.into_iter().chain(None))
527562
}
563+
// No successors
528564
UnwindResume
529565
| UnwindTerminate(_)
530566
| CoroutineDrop
531567
| Return
532568
| Unreachable
533569
| TailCall { .. }
534-
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
570+
| Call { target: None, unwind: _, .. } => {
571+
(&mut []).into_iter().chain(None.into_iter().chain(None))
572+
}
573+
// Multiple successors
535574
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
536-
targets.iter_mut().chain(Some(u))
575+
targets.iter_mut().chain(Some(u).into_iter().chain(None))
576+
}
577+
InlineAsm { ref mut targets, unwind: _, .. } => {
578+
targets.iter_mut().chain(None.into_iter().chain(None))
579+
}
580+
SwitchInt { ref mut targets, .. } => {
581+
targets.targets.iter_mut().chain(None.into_iter().chain(None))
537582
}
538-
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
539-
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
583+
// FalseEdge
540584
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
541-
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
585+
slice::from_mut(real_target)
586+
.into_iter()
587+
.chain(Some(imaginary_target).into_iter().chain(None))
542588
}
543589
}
544590
}
@@ -671,8 +717,10 @@ impl<'tcx> TerminatorKind<'tcx> {
671717

672718
Goto { target } => TerminatorEdges::Single(target),
673719

720+
// FIXME: Maybe we need also TerminatorEdges::Trio for async drop
721+
// (target + unwind + dropline)
674722
Assert { target, unwind, expected: _, msg: _, cond: _ }
675-
| Drop { target, unwind, place: _, replace: _ }
723+
| Drop { target, unwind, place: _, replace: _, drop: _, async_fut: _ }
676724
| FalseUnwind { real_target: target, unwind } => match unwind {
677725
UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
678726
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
@@ -762,6 +762,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
762762
target: success,
763763
unwind: UnwindAction::Continue,
764764
replace: false,
765+
drop: None,
766+
async_fut: None,
765767
},
766768
);
767769
this.diverge_from(block);

compiler/rustc_mir_build/src/builder/scope.rs

+8
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ impl DropTree {
405405
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
406406
place: drop_node.data.local.into(),
407407
replace: false,
408+
drop: None,
409+
async_fut: None,
408410
};
409411
cfg.terminate(block, drop_node.data.source_info, terminator);
410412
}
@@ -848,6 +850,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
848850
target: next,
849851
unwind: UnwindAction::Continue,
850852
replace: false,
853+
drop: None,
854+
async_fut: None,
851855
},
852856
);
853857
block = next;
@@ -1371,6 +1375,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13711375
target: assign,
13721376
unwind: UnwindAction::Cleanup(assign_unwind),
13731377
replace: true,
1378+
drop: None,
1379+
async_fut: None,
13741380
},
13751381
);
13761382
self.diverge_from(block);
@@ -1510,6 +1516,8 @@ fn build_scope_drops<'tcx>(
15101516
target: next,
15111517
unwind: UnwindAction::Continue,
15121518
replace: false,
1519+
drop: None,
1520+
async_fut: None,
15131521
},
15141522
);
15151523
block = next;

0 commit comments

Comments
 (0)