storage_conflicts
}
-fn compute_layout<'tcx>(
+/// Validates the typeck view of the generator against the actual set of types retained between
+/// yield points.
+fn sanitize_witness<'tcx>(
tcx: TyCtxt<'tcx>,
- source: MirSource<'tcx>,
+ body: &Body<'tcx>,
+ did: DefId,
+ witness: Ty<'tcx>,
upvars: &Vec<Ty<'tcx>>,
- interior: Ty<'tcx>,
- always_live_locals: &storage::AlwaysLiveLocals,
- movable: bool,
- body: &mut Body<'tcx>,
-) -> (
- FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
- GeneratorLayout<'tcx>,
- IndexVec<BasicBlock, Option<BitSet<Local>>>,
+ retained: &BitSet<Local>,
) {
- // Use a liveness analysis to compute locals which are live across a suspension point
- let LivenessInfo {
- live_locals,
- live_locals_at_suspension_points,
- storage_conflicts,
- storage_liveness,
- } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable);
-
- // Erase regions from the types passed in from typeck so we can compare them with
- // MIR types
let allowed_upvars = tcx.erase_regions(upvars);
- let allowed = match interior.kind {
+ let allowed = match witness.kind {
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
- _ => bug!(),
+ _ => {
+ tcx.sess.delay_span_bug(
+ body.span,
+ &format!("unexpected generator witness type {:?}", witness.kind),
+ );
+ return;
+ }
};
- let param_env = tcx.param_env(source.def_id());
+ let param_env = tcx.param_env(did);
for (local, decl) in body.local_decls.iter_enumerated() {
- // Ignore locals which are internal or not live
- if !live_locals.contains(local) || decl.internal {
+ // Ignore locals which are internal or not retained between yields.
+ if !retained.contains(local) || decl.internal {
continue;
}
let decl_ty = tcx.normalize_erasing_regions(param_env, decl.ty);
"Broken MIR: generator contains type {} in MIR, \
but typeck only knows about {}",
decl.ty,
- interior
+ witness,
);
}
}
+}
+
+fn compute_layout<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ source: MirSource<'tcx>,
+ upvars: &Vec<Ty<'tcx>>,
+ interior: Ty<'tcx>,
+ always_live_locals: &storage::AlwaysLiveLocals,
+ movable: bool,
+ body: &mut Body<'tcx>,
+) -> (
+ FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
+ GeneratorLayout<'tcx>,
+ IndexVec<BasicBlock, Option<BitSet<Local>>>,
+) {
+ // Use a liveness analysis to compute locals which are live across a suspension point
+ let LivenessInfo {
+ live_locals,
+ live_locals_at_suspension_points,
+ storage_conflicts,
+ storage_liveness,
+ } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable);
+
+ sanitize_witness(tcx, body, source.def_id(), interior, upvars, &live_locals);
// Gather live local types and their indices.
let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();