1
Fork 0

Check the base of the place too!

This commit is contained in:
Michael Goulet 2024-04-05 16:48:12 -04:00
parent 0f13bd436b
commit 49c4ebcc40
3 changed files with 48 additions and 6 deletions

View file

@ -71,7 +71,7 @@
use rustc_data_structures::unord::UnordMap; use rustc_data_structures::unord::UnordMap;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind};
use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::{self, dump_mir, MirPass}; use rustc_middle::mir::{self, dump_mir, MirPass};
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt};
@ -149,17 +149,25 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
bug!("we ran out of parent captures!") bug!("we ran out of parent captures!")
}; };
let PlaceBase::Upvar(parent_base) = parent_capture.place.base else {
bug!("expected capture to be an upvar");
};
let PlaceBase::Upvar(child_base) = child_capture.place.base else {
bug!("expected capture to be an upvar");
};
assert!( assert!(
child_capture.place.projections.len() >= parent_capture.place.projections.len() child_capture.place.projections.len() >= parent_capture.place.projections.len()
); );
// A parent matches a child they share the same prefix of projections. // A parent matches a child they share the same prefix of projections.
// The child may have more, if it is capturing sub-fields out of // The child may have more, if it is capturing sub-fields out of
// something that is captured by-move in the parent closure. // something that is captured by-move in the parent closure.
if !std::iter::zip( if parent_base.var_path.hir_id != child_base.var_path.hir_id
&child_capture.place.projections, || !std::iter::zip(
&parent_capture.place.projections, &child_capture.place.projections,
) &parent_capture.place.projections,
.all(|(child, parent)| child.kind == parent.kind) )
.all(|(child, parent)| child.kind == parent.kind)
{ {
// Make sure the field was used at least once. // Make sure the field was used at least once.
assert!( assert!(
@ -217,6 +225,12 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
} }
} }
// Pop the last parent capture
if field_used_at_least_once {
let _ = parent_captures.next().unwrap();
}
assert_eq!(parent_captures.next(), None, "leftover parent captures?");
if coroutine_kind == ty::ClosureKind::FnOnce { if coroutine_kind == ty::ClosureKind::FnOnce {
assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len());
return; return;

View file

@ -0,0 +1,27 @@
//@ aux-build:block-on.rs
//@ edition:2021
//@ run-pass
//@ check-run-results
#![feature(async_closure)]
extern crate block_on;
async fn call_once(f: impl async FnOnce()) {
f().await;
}
async fn async_main() {
let x = &mut 0;
let y = &mut 0;
let c = async || {
*x = 1;
*y = 2;
};
call_once(c).await;
println!("{x} {y}");
}
fn main() {
block_on::block_on(async_main());
}

View file

@ -0,0 +1 @@
1 2