Skip to content

Commit 15de84f

Browse files
committed
End locals' live range before suspending coroutine
State transforms retains storage statements for locals that are not stored inside a coroutine. It ensures those locals are live when resuming by inserting StorageLive as appropriate. It forgot to end the storage of those locals when suspending, which is fixed here. While the end of live range is implicit when executing return, it is nevertheless useful for inliner which would otherwise extend the live range beyond return.
1 parent 8a37655 commit 15de84f

5 files changed

+27
-1
lines changed

compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,26 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
527527
resume_arg
528528
};
529529

530+
let storage_liveness: GrowableBitSet<Local> =
531+
self.storage_liveness[block].clone().unwrap().into();
532+
533+
for i in 0..self.always_live_locals.domain_size() {
534+
let l = Local::new(i);
535+
let needs_storage_dead = storage_liveness.contains(l)
536+
&& !self.remap.contains_key(&l)
537+
&& !self.always_live_locals.contains(l);
538+
if needs_storage_dead {
539+
data.statements
540+
.push(Statement { source_info, kind: StatementKind::StorageDead(l) });
541+
}
542+
}
543+
530544
self.suspension_points.push(SuspensionPoint {
531545
state,
532546
resume,
533547
resume_arg,
534548
drop,
535-
storage_liveness: self.storage_liveness[block].clone().unwrap().into(),
549+
storage_liveness,
536550
});
537551

538552
VariantIdx::new(state)

tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
178178
StorageLive(_20);
179179
_20 = ();
180180
_0 = Poll::<()>::Pending;
181+
StorageDead(_3);
182+
StorageDead(_4);
183+
StorageDead(_19);
184+
StorageDead(_20);
181185
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 3;
182186
return;
183187
}
@@ -276,6 +280,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
276280
StorageLive(_36);
277281
_36 = ();
278282
_0 = Poll::<()>::Pending;
283+
StorageDead(_21);
284+
StorageDead(_35);
285+
StorageDead(_36);
279286
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 4;
280287
return;
281288
}

tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24
5555
StorageLive(_7);
5656
_7 = ();
5757
_0 = CoroutineState::<(), ()>::Yielded(move _7);
58+
StorageDead(_4);
59+
StorageDead(_6);
60+
StorageDead(_7);
5861
discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))) = 3;
5962
return;
6063
}

tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
+
9090
+ bb6: {
9191
+ _1 = CoroutineState::<i32, bool>::Yielded(move _8);
92+
+ StorageDead(_8);
9293
+ discriminant((*_6)) = 3;
9394
+ goto -> bb2;
9495
+ }

tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
+
104104
+ bb8: {
105105
+ _1 = CoroutineState::<i32, bool>::Yielded(move _8);
106+
+ StorageDead(_8);
106107
+ discriminant((*_6)) = 3;
107108
+ goto -> bb4;
108109
+ }

0 commit comments

Comments
 (0)