Don't create interior type variable in check_closure
This commit is contained in:
parent
5a08ba6545
commit
71dacdfa0f
@ -94,7 +94,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||||||
// Resume type defaults to `()` if the coroutine has no argument.
|
// Resume type defaults to `()` if the coroutine has no argument.
|
||||||
let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| Ty::new_unit(tcx));
|
let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| Ty::new_unit(tcx));
|
||||||
|
|
||||||
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
|
fcx.coroutine_types = Some(CoroutineTypes { resume_ty, yield_ty });
|
||||||
}
|
}
|
||||||
|
|
||||||
GatherLocalsVisitor::new(fcx).visit_body(body);
|
GatherLocalsVisitor::new(fcx).visit_body(body);
|
||||||
@ -146,20 +146,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||||||
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
|
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
|
||||||
fcx.check_return_expr(body.value, false);
|
fcx.check_return_expr(body.value, false);
|
||||||
|
|
||||||
// We insert the deferred_coroutine_interiors entry after visiting the body.
|
|
||||||
// This ensures that all nested coroutines appear before the entry of this coroutine.
|
|
||||||
// resolve_coroutine_interiors relies on this property.
|
|
||||||
let coroutine_ty = if let Some(hir::ClosureKind::Coroutine(_)) = closure_kind {
|
|
||||||
let interior = fcx
|
|
||||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
|
|
||||||
fcx.deferred_coroutine_interiors.borrow_mut().push((fn_def_id, body.id(), interior));
|
|
||||||
|
|
||||||
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
|
|
||||||
Some(CoroutineTypes { resume_ty, yield_ty, interior })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Finalize the return check by taking the LUB of the return types
|
// Finalize the return check by taking the LUB of the return types
|
||||||
// we saw and assigning it to the expected return type. This isn't
|
// we saw and assigning it to the expected return type. This isn't
|
||||||
// really expected to fail, since the coercions would have failed
|
// really expected to fail, since the coercions would have failed
|
||||||
@ -195,7 +181,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||||||
check_lang_start_fn(tcx, fn_sig, fn_def_id);
|
check_lang_start_fn(tcx, fn_sig, fn_def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutine_ty
|
fcx.coroutine_types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) {
|
fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) {
|
||||||
|
@ -105,59 +105,76 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span: self.tcx.def_span(expr_def_id),
|
span: self.tcx.def_span(expr_def_id),
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(CoroutineTypes { resume_ty, yield_ty, interior }) = coroutine_types {
|
match closure.kind {
|
||||||
let coroutine_args = ty::CoroutineArgs::new(
|
hir::ClosureKind::Closure => {
|
||||||
self.tcx,
|
assert_eq!(coroutine_types, None);
|
||||||
ty::CoroutineArgsParts {
|
// Tuple up the arguments and insert the resulting function type into
|
||||||
parent_args,
|
// the `closures` table.
|
||||||
resume_ty,
|
let sig = bound_sig.map_bound(|sig| {
|
||||||
yield_ty,
|
self.tcx.mk_fn_sig(
|
||||||
return_ty: liberated_sig.output(),
|
[Ty::new_tup(self.tcx, sig.inputs())],
|
||||||
witness: interior,
|
sig.output(),
|
||||||
tupled_upvars_ty,
|
sig.c_variadic,
|
||||||
},
|
sig.unsafety,
|
||||||
);
|
sig.abi,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
return Ty::new_coroutine(self.tcx, expr_def_id.to_def_id(), coroutine_args.args);
|
debug!(?sig, ?opt_kind);
|
||||||
|
|
||||||
|
let closure_kind_ty = match opt_kind {
|
||||||
|
Some(kind) => Ty::from_closure_kind(self.tcx, kind),
|
||||||
|
|
||||||
|
// Create a type variable (for now) to represent the closure kind.
|
||||||
|
// It will be unified during the upvar inference phase (`upvar.rs`)
|
||||||
|
None => self.next_root_ty_var(TypeVariableOrigin {
|
||||||
|
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
||||||
|
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||||
|
span: expr_span,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let closure_args = ty::ClosureArgs::new(
|
||||||
|
self.tcx,
|
||||||
|
ty::ClosureArgsParts {
|
||||||
|
parent_args,
|
||||||
|
closure_kind_ty,
|
||||||
|
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(self.tcx, sig),
|
||||||
|
tupled_upvars_ty,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_args.args)
|
||||||
|
}
|
||||||
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
|
let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
|
||||||
|
bug!("expected coroutine to have yield/resume types");
|
||||||
|
};
|
||||||
|
let interior = fcx.next_ty_var(TypeVariableOrigin {
|
||||||
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
|
span: body.value.span,
|
||||||
|
});
|
||||||
|
fcx.deferred_coroutine_interiors.borrow_mut().push((
|
||||||
|
expr_def_id,
|
||||||
|
body.id(),
|
||||||
|
interior,
|
||||||
|
));
|
||||||
|
|
||||||
|
let coroutine_args = ty::CoroutineArgs::new(
|
||||||
|
self.tcx,
|
||||||
|
ty::CoroutineArgsParts {
|
||||||
|
parent_args,
|
||||||
|
resume_ty,
|
||||||
|
yield_ty,
|
||||||
|
return_ty: liberated_sig.output(),
|
||||||
|
witness: interior,
|
||||||
|
tupled_upvars_ty,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ty::new_coroutine(self.tcx, expr_def_id.to_def_id(), coroutine_args.args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuple up the arguments and insert the resulting function type into
|
|
||||||
// the `closures` table.
|
|
||||||
let sig = bound_sig.map_bound(|sig| {
|
|
||||||
self.tcx.mk_fn_sig(
|
|
||||||
[Ty::new_tup(self.tcx, sig.inputs())],
|
|
||||||
sig.output(),
|
|
||||||
sig.c_variadic,
|
|
||||||
sig.unsafety,
|
|
||||||
sig.abi,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!(?sig, ?opt_kind);
|
|
||||||
|
|
||||||
let closure_kind_ty = match opt_kind {
|
|
||||||
Some(kind) => Ty::from_closure_kind(self.tcx, kind),
|
|
||||||
|
|
||||||
// Create a type variable (for now) to represent the closure kind.
|
|
||||||
// It will be unified during the upvar inference phase (`upvar.rs`)
|
|
||||||
None => self.next_root_ty_var(TypeVariableOrigin {
|
|
||||||
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
|
||||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
|
||||||
span: expr_span,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
let closure_args = ty::ClosureArgs::new(
|
|
||||||
self.tcx,
|
|
||||||
ty::ClosureArgsParts {
|
|
||||||
parent_args,
|
|
||||||
closure_kind_ty,
|
|
||||||
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(self.tcx, sig),
|
|
||||||
tupled_upvars_ty,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_args.args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the expected type, figures out what it can about this closure we
|
/// Given the expected type, figures out what it can about this closure we
|
||||||
|
@ -15,6 +15,7 @@ use crate::errors::{
|
|||||||
use crate::fatally_break_rust;
|
use crate::fatally_break_rust;
|
||||||
use crate::method::SelfSource;
|
use crate::method::SelfSource;
|
||||||
use crate::type_error_struct;
|
use crate::type_error_struct;
|
||||||
|
use crate::CoroutineTypes;
|
||||||
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
|
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
|
||||||
use crate::{
|
use crate::{
|
||||||
report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
|
report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
|
||||||
@ -3164,8 +3165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
src: &'tcx hir::YieldSource,
|
src: &'tcx hir::YieldSource,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
match self.resume_yield_tys {
|
match self.coroutine_types {
|
||||||
Some((resume_ty, yield_ty)) => {
|
Some(CoroutineTypes { resume_ty, yield_ty }) => {
|
||||||
self.check_expr_coercible_to_type(value, yield_ty, None);
|
self.check_expr_coercible_to_type(value, yield_ty, None);
|
||||||
|
|
||||||
resume_ty
|
resume_ty
|
||||||
|
@ -5,7 +5,7 @@ mod checks;
|
|||||||
mod suggestions;
|
mod suggestions;
|
||||||
|
|
||||||
use crate::coercion::DynamicCoerceMany;
|
use crate::coercion::DynamicCoerceMany;
|
||||||
use crate::{Diverges, EnclosingBreakables, Inherited};
|
use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
|
||||||
use rustc_errors::{DiagCtxt, ErrorGuaranteed};
|
use rustc_errors::{DiagCtxt, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
@ -68,7 +68,7 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||||||
/// First span of a return site that we find. Used in error messages.
|
/// First span of a return site that we find. Used in error messages.
|
||||||
pub(super) ret_coercion_span: Cell<Option<Span>>,
|
pub(super) ret_coercion_span: Cell<Option<Span>>,
|
||||||
|
|
||||||
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
|
pub(super) coroutine_types: Option<CoroutineTypes<'tcx>>,
|
||||||
|
|
||||||
/// Whether the last checked node generates a divergence (e.g.,
|
/// Whether the last checked node generates a divergence (e.g.,
|
||||||
/// `return` will set this to `Always`). In general, when entering
|
/// `return` will set this to `Always`). In general, when entering
|
||||||
@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
err_count_on_creation: inh.tcx.dcx().err_count(),
|
err_count_on_creation: inh.tcx.dcx().err_count(),
|
||||||
ret_coercion: None,
|
ret_coercion: None,
|
||||||
ret_coercion_span: Cell::new(None),
|
ret_coercion_span: Cell::new(None),
|
||||||
resume_yield_tys: None,
|
coroutine_types: None,
|
||||||
diverges: Cell::new(Diverges::Maybe),
|
diverges: Cell::new(Diverges::Maybe),
|
||||||
enclosing_breakables: RefCell::new(EnclosingBreakables {
|
enclosing_breakables: RefCell::new(EnclosingBreakables {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
|
@ -295,15 +295,13 @@ fn typeck_with_fallback<'tcx>(
|
|||||||
/// When `check_fn` is invoked on a coroutine (i.e., a body that
|
/// When `check_fn` is invoked on a coroutine (i.e., a body that
|
||||||
/// includes yield), it returns back some information about the yield
|
/// includes yield), it returns back some information about the yield
|
||||||
/// points.
|
/// points.
|
||||||
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
struct CoroutineTypes<'tcx> {
|
struct CoroutineTypes<'tcx> {
|
||||||
/// Type of coroutine argument / values returned by `yield`.
|
/// Type of coroutine argument / values returned by `yield`.
|
||||||
resume_ty: Ty<'tcx>,
|
resume_ty: Ty<'tcx>,
|
||||||
|
|
||||||
/// Type of value that is yielded.
|
/// Type of value that is yielded.
|
||||||
yield_ty: Ty<'tcx>,
|
yield_ty: Ty<'tcx>,
|
||||||
|
|
||||||
/// Types that are captured (see `CoroutineInterior` for more).
|
|
||||||
interior: Ty<'tcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user