]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/closure.rs
Rollup merge of #75485 - RalfJung:pin, r=nagisa
[rust.git] / src / librustc_typeck / check / closure.rs
index 8b18e759026b1bb1c6678c7c578506c612582af7..c7f9e9d63e03c576a21a595dd72144437b5d5040 100644 (file)
@@ -11,7 +11,7 @@
 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;
@@ -76,60 +76,44 @@ fn check_closure(
         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
@@ -149,18 +133,29 @@ fn check_closure(
             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);
 
@@ -206,11 +201,15 @@ fn deduce_expectations_from_obligations(
                     obligation.predicate
                 );
 
-                if let &ty::PredicateKind::Projection(proj_predicate) = obligation.predicate.kind()
+                if let ty::PredicateAtom::Projection(proj_predicate) =
+                    obligation.predicate.skip_binders()
                 {
                     // Given a Projection predicate, we can potentially infer
                     // the complete signature.
-                    self.deduce_sig_from_projection(Some(obligation.cause.span), proj_predicate)
+                    self.deduce_sig_from_projection(
+                        Some(obligation.cause.span),
+                        ty::Binder::bind(proj_predicate),
+                    )
                 } else {
                     None
                 }
@@ -627,8 +626,13 @@ fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty
         // where R is the return type we are expecting. This type `T`
         // will be our output.
         let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
-            if let &ty::PredicateKind::Projection(proj_predicate) = obligation.predicate.kind() {
-                self.deduce_future_output_from_projection(obligation.cause.span, proj_predicate)
+            if let ty::PredicateAtom::Projection(proj_predicate) =
+                obligation.predicate.skip_binders()
+            {
+                self.deduce_future_output_from_projection(
+                    obligation.cause.span,
+                    ty::Binder::bind(proj_predicate),
+                )
             } else {
                 None
             }