Skip to content

Commit 49c4ebc

Browse files
Check the base of the place too!
1 parent 0f13bd4 commit 49c4ebc

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

compiler/rustc_mir_transform/src/coroutine/by_move_body.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
7272
use rustc_data_structures::unord::UnordMap;
7373
use rustc_hir as hir;
74-
use rustc_middle::hir::place::{Projection, ProjectionKind};
74+
use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind};
7575
use rustc_middle::mir::visit::MutVisitor;
7676
use rustc_middle::mir::{self, dump_mir, MirPass};
7777
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt};
@@ -149,17 +149,25 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
149149
bug!("we ran out of parent captures!")
150150
};
151151

152+
let PlaceBase::Upvar(parent_base) = parent_capture.place.base else {
153+
bug!("expected capture to be an upvar");
154+
};
155+
let PlaceBase::Upvar(child_base) = child_capture.place.base else {
156+
bug!("expected capture to be an upvar");
157+
};
158+
152159
assert!(
153160
child_capture.place.projections.len() >= parent_capture.place.projections.len()
154161
);
155162
// A parent matches a child they share the same prefix of projections.
156163
// The child may have more, if it is capturing sub-fields out of
157164
// something that is captured by-move in the parent closure.
158-
if !std::iter::zip(
159-
&child_capture.place.projections,
160-
&parent_capture.place.projections,
161-
)
162-
.all(|(child, parent)| child.kind == parent.kind)
165+
if parent_base.var_path.hir_id != child_base.var_path.hir_id
166+
|| !std::iter::zip(
167+
&child_capture.place.projections,
168+
&parent_capture.place.projections,
169+
)
170+
.all(|(child, parent)| child.kind == parent.kind)
163171
{
164172
// Make sure the field was used at least once.
165173
assert!(
@@ -217,6 +225,12 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
217225
}
218226
}
219227

228+
// Pop the last parent capture
229+
if field_used_at_least_once {
230+
let _ = parent_captures.next().unwrap();
231+
}
232+
assert_eq!(parent_captures.next(), None, "leftover parent captures?");
233+
220234
if coroutine_kind == ty::ClosureKind::FnOnce {
221235
assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len());
222236
return;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ aux-build:block-on.rs
2+
//@ edition:2021
3+
//@ run-pass
4+
//@ check-run-results
5+
6+
#![feature(async_closure)]
7+
8+
extern crate block_on;
9+
10+
async fn call_once(f: impl async FnOnce()) {
11+
f().await;
12+
}
13+
14+
async fn async_main() {
15+
let x = &mut 0;
16+
let y = &mut 0;
17+
let c = async || {
18+
*x = 1;
19+
*y = 2;
20+
};
21+
call_once(c).await;
22+
println!("{x} {y}");
23+
}
24+
25+
fn main() {
26+
block_on::block_on(async_main());
27+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1 2

0 commit comments

Comments
 (0)