Check yield terminator's resume type in borrowck
This commit is contained in:
parent
139fb22146
commit
1d48f69d65
12 changed files with 190 additions and 36 deletions
|
@ -94,31 +94,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
|
||||
body.yield_ty(),
|
||||
universal_regions.yield_ty
|
||||
);
|
||||
|
||||
// We will not have a universal_regions.yield_ty if we yield (by accident)
|
||||
// outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug
|
||||
// because we don't want to panic in an assert here if we've already got errors.
|
||||
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
|
||||
self.tcx().dcx().span_delayed_bug(
|
||||
body.span,
|
||||
format!(
|
||||
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
|
||||
body.yield_ty(),
|
||||
universal_regions.yield_ty,
|
||||
),
|
||||
if let Some(mir_yield_ty) = body.yield_ty() {
|
||||
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||
self.equate_normalized_input_or_output(
|
||||
universal_regions.yield_ty.unwrap(),
|
||||
mir_yield_ty,
|
||||
yield_span,
|
||||
);
|
||||
}
|
||||
|
||||
if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
|
||||
(body.yield_ty(), universal_regions.yield_ty)
|
||||
{
|
||||
if let Some(mir_resume_ty) = body.resume_ty() {
|
||||
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||
self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
|
||||
self.equate_normalized_input_or_output(
|
||||
universal_regions.resume_ty.unwrap(),
|
||||
mir_resume_ty,
|
||||
yield_span,
|
||||
);
|
||||
}
|
||||
|
||||
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
|
||||
|
|
|
@ -183,6 +183,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
|
|||
match ty_context {
|
||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||
| TyContext::ResumeTy(SourceInfo { span, .. })
|
||||
| TyContext::UserTy(span)
|
||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||
|
|
|
@ -1450,13 +1450,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::Yield { value, .. } => {
|
||||
TerminatorKind::Yield { value, resume_arg, .. } => {
|
||||
self.check_operand(value, term_location);
|
||||
|
||||
let value_ty = value.ty(body, tcx);
|
||||
match body.yield_ty() {
|
||||
None => span_mirbug!(self, term, "yield in non-coroutine"),
|
||||
Some(ty) => {
|
||||
let value_ty = value.ty(body, tcx);
|
||||
if let Err(terr) = self.sub_types(
|
||||
value_ty,
|
||||
ty,
|
||||
|
@ -1474,6 +1474,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
match body.resume_ty() {
|
||||
None => span_mirbug!(self, term, "yield in non-coroutine"),
|
||||
Some(ty) => {
|
||||
let resume_ty = resume_arg.ty(body, tcx);
|
||||
if let Err(terr) = self.sub_types(
|
||||
ty,
|
||||
resume_ty.ty,
|
||||
term_location.to_locations(),
|
||||
ConstraintCategory::Yield,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
term,
|
||||
"type of resume place is {:?}, but the resume type is {:?}: {:?}",
|
||||
resume_ty,
|
||||
ty,
|
||||
terr
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,8 @@ pub struct UniversalRegions<'tcx> {
|
|||
pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
|
||||
|
||||
pub yield_ty: Option<Ty<'tcx>>,
|
||||
|
||||
pub resume_ty: Option<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
/// The "defining type" for this MIR. The key feature of the "defining
|
||||
|
@ -525,9 +527,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
|
||||
debug!("build: local regions = {}..{}", first_local_index, num_universals);
|
||||
|
||||
let yield_ty = match defining_ty {
|
||||
DefiningTy::Coroutine(_, args) => Some(args.as_coroutine().yield_ty()),
|
||||
_ => None,
|
||||
let (resume_ty, yield_ty) = match defining_ty {
|
||||
DefiningTy::Coroutine(_, args) => {
|
||||
let tys = args.as_coroutine();
|
||||
(Some(tys.resume_ty()), Some(tys.yield_ty()))
|
||||
}
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
UniversalRegions {
|
||||
|
@ -541,6 +546,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
unnormalized_output_ty: *unnormalized_output_ty,
|
||||
unnormalized_input_tys,
|
||||
yield_ty,
|
||||
resume_ty,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue