Skip to content

Commit ba50bc5

Browse files
authored
Rollup merge of #70367 - nikomatsakis:issue-69307, r=Aaron1011
save/restore `pessimistic_yield` when entering bodies This flag is used to make the execution order around `+=` operators pessimistic. Failure to save/restore the flag was causing independent async blocks to effect one another, leading to strange ICEs and failed assumptions. Fixes #69307 r? @Zoxc
2 parents e89cb07 + 563152d commit ba50bc5

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

src/librustc_passes/region.rs

+9
Original file line numberDiff line numberDiff line change
@@ -717,9 +717,17 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
717717
self.cx.parent
718718
);
719719

720+
// Save all state that is specific to the outer function
721+
// body. These will be restored once down below, once we've
722+
// visited the body.
720723
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
721724
let outer_cx = self.cx;
722725
let outer_ts = mem::take(&mut self.terminating_scopes);
726+
// The 'pessimistic yield' flag is set to true when we are
727+
// processing a `+=` statement and have to make pessimistic
728+
// control flow assumptions. This doesn't apply to nested
729+
// bodies within the `+=` statements. See #69307.
730+
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
723731
self.terminating_scopes.insert(body.value.hir_id.local_id);
724732

725733
if let Some(root_id) = self.cx.root_id {
@@ -771,6 +779,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
771779
self.expr_and_pat_count = outer_ec;
772780
self.cx = outer_cx;
773781
self.terminating_scopes = outer_ts;
782+
self.pessimistic_yield = outer_pessimistic_yield;
774783
}
775784

776785
fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Regression test for #69307
2+
//
3+
// Having a `async { .. foo.await .. }` block appear inside of a `+=`
4+
// expression was causing an ICE due to a failure to save/restore
5+
// state in the AST numbering pass when entering a nested body.
6+
//
7+
// check-pass
8+
// edition:2018
9+
10+
fn block_on<F>(_: F) -> usize {
11+
0
12+
}
13+
14+
fn main() {}
15+
16+
async fn bar() {
17+
let mut sum = 0;
18+
sum += {
19+
block_on(async {
20+
baz().await;
21+
let mut inner = 1;
22+
inner += block_on(async {
23+
baz().await;
24+
0
25+
})
26+
})
27+
};
28+
}
29+
30+
async fn baz() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Regression test for #69307
2+
//
3+
// Having a `async { .. foo.await .. }` block appear inside of a `+=`
4+
// expression was causing an ICE due to a failure to save/restore
5+
// state in the AST numbering pass when entering a nested body.
6+
//
7+
// check-pass
8+
// edition:2018
9+
10+
fn block_on<F>(_: F) -> usize {
11+
0
12+
}
13+
14+
fn main() {}
15+
16+
async fn bar() {
17+
let mut sum = 0;
18+
sum += block_on(async {
19+
baz().await;
20+
});
21+
}
22+
23+
async fn baz() {}

0 commit comments

Comments
 (0)