1
Fork 0

Replace tuple of infer vars for upvar_tys with single infer var

This commit allows us to decide the number of captures required after
completing capture ananysis, which is required as part of implementing
RFC-2229.

Co-authored-by: Aman Arora <me@aman-arora.com>
Co-authored-by: Jenny Wills <wills.jenniferg@gmail.com>
This commit is contained in:
Roxane 2020-07-19 17:26:51 -04:00 committed by Aman Arora
parent 25d2d09da7
commit dc183702da
23 changed files with 178 additions and 95 deletions

View file

@ -81,19 +81,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
);
let tupled_upvars_ty =
self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| {
upvars.iter().map(|(&var_hir_id, _)| {
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
self.infcx.next_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish upvar inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.hir().span(var_hir_id),
})
})
}));
let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.hir().span(expr.hir_id),
});
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{

View file

@ -39,6 +39,7 @@ use crate::astconv::AstConv;
use crate::check::FnCtxt;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, InferOk, InferResult};
use rustc_middle::ty::adjustment::{
@ -221,11 +222,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
ty::Closure(_, substs_a) => {
ty::Closure(closure_def_id_a, substs_a) => {
// Non-capturing closures are coercible to
// function pointers or unsafe function pointers.
// It cannot convert closures that require unsafe.
self.coerce_closure_to_fn(a, substs_a, b)
self.coerce_closure_to_fn(a, closure_def_id_a, substs_a, b)
}
_ => {
// Otherwise, just use unification rules.
@ -762,6 +763,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
fn coerce_closure_to_fn(
&self,
a: Ty<'tcx>,
closure_def_id_a: DefId,
substs_a: SubstsRef<'tcx>,
b: Ty<'tcx>,
) -> CoerceResult<'tcx> {
@ -772,7 +774,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let b = self.shallow_resolve(b);
match b.kind() {
ty::FnPtr(fn_ty) if substs_a.as_closure().upvar_tys().next().is_none() => {
// At this point we haven't done capture analysis, which means
// that the ClosureSubsts just contains an inference variable instead
// of tuple of captured types.
//
// All we care here is if any variable is being captured and not the exact paths,
// so we check `upvars_mentioned` for root variables being captured.
ty::FnPtr(fn_ty)
if self
.tcx
.upvars_mentioned(closure_def_id_a.expect_local())
.map_or(true, |u| u.is_empty()) =>
{
// We coerce the closure, which has fn type
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
// to
@ -906,8 +919,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Function items or non-capturing closures of differing IDs or InternalSubsts.
let (a_sig, b_sig) = {
let is_capturing_closure = |ty| {
if let &ty::Closure(_, substs) = ty {
substs.as_closure().upvar_tys().next().is_some()
if let &ty::Closure(closure_def_id, _substs) = ty {
self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some()
} else {
false
}

View file

@ -202,9 +202,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
closure_hir_id, substs, final_upvar_tys
);
for (upvar_ty, final_upvar_ty) in substs.upvar_tys().zip(final_upvar_tys) {
self.demand_suptype(span, upvar_ty, final_upvar_ty);
}
// Build a tuple (U0..Un) of the final upvar types U0..Un
// and unify the upvar tupe type in the closure with it:
let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter());
self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type);
// If we are also inferred the closure kind here,
// process any deferred resolutions.