use rustc_infer::infer::{InferOk, InferResult};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
let generator_types =
check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1;
- let base_substs = InternalSubsts::identity_for_item(
+ let parent_substs = InternalSubsts::identity_for_item(
self.tcx,
self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
);
- // HACK(eddyb) this hardcodes indices into substs but it should rely on
- // `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead.
- // That would also remove the need for most of the inference variables,
- // as they immediately unified with the actual type below, including
- // the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods.
- let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 };
- let substs =
- base_substs.extend_to(self.tcx, expr_def_id.to_def_id(), |param, _| match param.kind {
- GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"),
- GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx {
- 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),
- })
- })
- },
- ))
- } else {
- // Create type variables (for now) to represent the various
- // pieces of information kept in `{Closure,Generic}Substs`.
- // They will either be unified below, or later during the upvar
- // inference phase (`upvar.rs`)
+
+ 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: expr.span,
+ span: self.tcx.hir().span(var_hir_id),
})
- }
- .into(),
- GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
- });
+ })
+ }));
+
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
- let generator_substs = substs.as_generator();
- self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty());
- self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty());
- self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty());
- self.demand_eqtype(expr.span, interior, generator_substs.witness());
-
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `GeneratorSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let generator_substs = ty::GeneratorSubsts::new(
+ self.tcx,
+ ty::GeneratorSubstsParts {
+ parent_substs,
+ resume_ty,
+ yield_ty,
+ return_ty: liberated_sig.output(),
+ witness: interior,
+ tupled_upvars_ty,
+ },
+ );
- return self.tcx.mk_generator(expr_def_id.to_def_id(), substs, movability);
+ return self.tcx.mk_generator(
+ expr_def_id.to_def_id(),
+ generator_substs.substs,
+ movability,
+ );
}
// Tuple up the arguments and insert the resulting function type into
expr_def_id, sig, opt_kind
);
- let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
- self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty());
+ let closure_kind_ty = match opt_kind {
+ Some(kind) => kind.to_ty(self.tcx),
- if let Some(kind) = opt_kind {
- self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty());
- }
+ // Create a type variable (for now) to represent the closure kind.
+ // It will be unified during the upvar inference phase (`upvar.rs`)
+ None => self.infcx.next_ty_var(TypeVariableOrigin {
+ // FIXME(eddyb) distinguish closure kind inference variables from the rest.
+ kind: TypeVariableOriginKind::ClosureSynthetic,
+ span: expr.span,
+ }),
+ };
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `ClosureSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let closure_substs = ty::ClosureSubsts::new(
+ self.tcx,
+ ty::ClosureSubstsParts {
+ parent_substs,
+ closure_kind_ty,
+ closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig),
+ tupled_upvars_ty,
+ },
+ );
- let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), substs);
+ let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs);
debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);