Rollup merge of #72764 - jonas-schievink:mind-the-tyerr, r=estebank

Be more careful around ty::Error in generators

cc https://github.com/rust-lang/rust/issues/72685

(doesn't close it because it's missing a reproduction to use as a test case)

r? @estebank
This commit is contained in:
Dylan DPC 2020-06-07 15:33:32 +02:00 committed by GitHub
commit 2cab88a33e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 31 deletions

View file

@ -669,6 +669,51 @@ fn compute_storage_conflicts(
storage_conflicts
}
/// Validates the typeck view of the generator against the actual set of types retained between
/// yield points.
fn sanitize_witness<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
did: DefId,
witness: Ty<'tcx>,
upvars: &Vec<Ty<'tcx>>,
retained: &BitSet<Local>,
) {
let allowed_upvars = tcx.erase_regions(upvars);
let allowed = match witness.kind {
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
_ => {
tcx.sess.delay_span_bug(
body.span,
&format!("unexpected generator witness type {:?}", witness.kind),
);
return;
}
};
let param_env = tcx.param_env(did);
for (local, decl) in body.local_decls.iter_enumerated() {
// 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);
// Sanity check that typeck knows about the type of locals which are
// live across a suspension point
if !allowed.contains(&decl_ty) && !allowed_upvars.contains(&decl_ty) {
span_bug!(
body.span,
"Broken MIR: generator contains type {} in MIR, \
but typeck only knows about {}",
decl.ty,
witness,
);
}
}
}
fn compute_layout<'tcx>(
tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
@ -690,35 +735,7 @@ fn compute_layout<'tcx>(
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 {
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
_ => bug!(),
};
let param_env = tcx.param_env(source.def_id());
for (local, decl) in body.local_decls.iter_enumerated() {
// Ignore locals which are internal or not live
if !live_locals.contains(local) || decl.internal {
continue;
}
let decl_ty = tcx.normalize_erasing_regions(param_env, decl.ty);
// Sanity check that typeck knows about the type of locals which are
// live across a suspension point
if !allowed.contains(&decl_ty) && !allowed_upvars.contains(&decl_ty) {
span_bug!(
body.span,
"Broken MIR: generator contains type {} in MIR, \
but typeck only knows about {}",
decl.ty,
interior
);
}
}
sanitize_witness(tcx, body, source.def_id(), interior, upvars, &live_locals);
// Gather live local types and their indices.
let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();

View file

@ -99,7 +99,7 @@ where
}
}
ty::Generator(_, substs, _) => {
ty::Generator(def_id, substs, _) => {
let substs = substs.as_generator();
for upvar_ty in substs.upvar_tys() {
queue_type(self, upvar_ty);
@ -108,7 +108,13 @@ where
let witness = substs.witness();
let interior_tys = match &witness.kind {
ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
_ => bug!(),
_ => {
tcx.sess.delay_span_bug(
tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
&format!("unexpected generator witness type {:?}", witness),
);
return Some(Err(AlwaysRequiresDrop));
}
};
for interior_ty in interior_tys {