Skip to content

Commit 59188cb

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 42dfac5 commit 59188cb

File tree

4 files changed

+26
-1
lines changed

4 files changed

+26
-1
lines changed

compiler/rustc_mir_transform/src/coroutine.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -529,12 +529,26 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
529529
resume_arg
530530
};
531531

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

540554
VariantIdx::new(state)

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

+7
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

+3
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-unwind.diff

+1
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)