Infer type of yield to be resume type

This commit is contained in:
Jonas Schievink 2020-01-25 02:27:51 +01:00
parent 25af2f66ce
commit 8a1227a67b
3 changed files with 24 additions and 10 deletions

View File

@ -92,11 +92,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.into(),
GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
});
if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
let generator_substs = substs.as_generator();
self.demand_eqtype(
expr.span,
self.tcx.mk_unit(), // WIP
resume_ty,
generator_substs.resume_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(

View File

@ -1796,9 +1796,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
src: &'tcx hir::YieldSource,
) -> Ty<'tcx> {
match self.yield_ty {
Some(ty) => {
self.check_expr_coercable_to_type(&value, ty);
match self.resume_yield_tys {
Some((resume_ty, yield_ty)) => {
self.check_expr_coercable_to_type(&value, yield_ty);
resume_ty
}
// Given that this `yield` expression was generated as a result of lowering a `.await`,
// we know that the yield type must be `()`; however, the context won't contain this
@ -1806,6 +1808,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// value's type against `()` (this check should always hold).
None if src == &hir::YieldSource::Await => {
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
self.tcx.mk_unit()
}
_ => {
struct_span_err!(
@ -1815,9 +1818,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"yield expression outside of generator literal"
)
.emit();
self.tcx.mk_unit()
}
}
self.tcx.mk_unit()
}
}

View File

@ -573,7 +573,7 @@ pub struct FnCtxt<'a, 'tcx> {
/// First span of a return site that we find. Used in error messages.
ret_coercion_span: RefCell<Option<Span>>,
yield_ty: Option<Ty<'tcx>>,
resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
ps: RefCell<UnsafetyState>,
@ -1248,6 +1248,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
/// includes yield), it returns back some information about the yield
/// points.
struct GeneratorTypes<'tcx> {
/// Type of generator argument / values returned by `yield`.
resume_ty: Ty<'tcx>,
/// Type of value that is yielded.
yield_ty: Ty<'tcx>,
@ -1308,7 +1311,11 @@ fn check_fn<'a, 'tcx>(
let yield_ty = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
fcx.yield_ty = Some(yield_ty);
// Resume type defaults to `()` if the generator has no argument.
let resume_ty = fn_sig.inputs().get(0).map(|ty| *ty).unwrap_or_else(|| tcx.mk_unit());
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
}
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id));
@ -1361,8 +1368,11 @@ fn check_fn<'a, 'tcx>(
let interior = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
Some(GeneratorTypes {
yield_ty: fcx.yield_ty.unwrap(),
resume_ty,
yield_ty,
interior,
movability: can_be_generator.unwrap(),
})
@ -2764,7 +2774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err_count_on_creation: inh.tcx.sess.err_count(),
ret_coercion: None,
ret_coercion_span: RefCell::new(None),
yield_ty: None,
resume_yield_tys: None,
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
diverges: Cell::new(Diverges::Maybe),
has_errors: Cell::new(false),