]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/nll/type_check/mod.rs
port the relate-types code from NLL type-check into a type-op
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / mod.rs
index ace012777c7a795132576e3cc5e6b3e10e1be29c..bbbe02fda6a84dd145035e0e6331b5117d3b100a 100644 (file)
@@ -42,7 +42,7 @@
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSelfTy, UserSubsts};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -975,127 +975,43 @@ fn relate_type_and_user_type(
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
-        let tcx = self.tcx();
-
         debug!(
-            "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
-            a, v, user_ty, locations
+            "relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
+            a, v, user_ty, locations,
         );
 
-        // The `TypeRelating` code assumes that "unresolved inference
-        // variables" appear in the "a" side, so flip `Contravariant`
-        // ambient variance to get the right relationship.
-        let v1 = ty::Contravariant.xform(v);
-
         match user_ty {
             UserTypeAnnotation::Ty(canonical_ty) => {
                 let (ty, _) = self.infcx
                     .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
 
-                self.relate_types(ty, v1, a, locations, category)?;
+                // The `TypeRelating` code assumes that "unresolved inference
+                // variables" appear in the "a" side, so flip `Contravariant`
+                // ambient variance to get the right relationship.
+                let v1 = ty::Contravariant.xform(v);
 
-                self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+                self.relate_types(ty, v1, a, locations, category)?;
             }
             UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
                 let (
-                    UserSubsts {
-                        substs,
-                        user_self_ty,
-                    },
+                    user_substs,
                     _,
                 ) = self.infcx
                     .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
 
-                let ty = self.tcx().type_of(def_id);
-                let ty = ty.subst(tcx, substs);
-                debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
-                let ty = self.normalize(ty, locations);
-
-                self.relate_types(ty, v1, a, locations, category)?;
-
-                if let Some(UserSelfTy {
-                    impl_def_id,
-                    self_ty,
-                }) = user_self_ty
-                {
-                    let impl_self_ty = tcx.type_of(impl_def_id);
-                    let impl_self_ty = impl_self_ty.subst(tcx, &substs);
-                    let impl_self_ty = self.normalize(impl_self_ty, locations);
-
-                    // There may be type variables in `substs` and hence
-                    // in `impl_self_ty`, but they should all have been
-                    // resolved to some fixed value during the first call
-                    // to `relate`, above. Therefore, if we use
-                    // `resolve_type_vars_if_possible` we should get to
-                    // something without type variables. This is important
-                    // because the `b` type in `relate_with_variance`
-                    // below is not permitted to have inference variables.
-                    let impl_self_ty = self.infcx.resolve_type_vars_if_possible(&impl_self_ty);
-                    assert!(!impl_self_ty.has_infer_types());
-
-                    self.eq_types(self_ty, impl_self_ty, locations, category)?;
-
-                    self.prove_predicate(
-                        ty::Predicate::WellFormed(impl_self_ty),
-                        locations,
-                        category,
-                    );
-                }
-
-                // Prove the predicates coming along with `def_id`.
-                //
-                // Also, normalize the `instantiated_predicates`
-                // because otherwise we wind up with duplicate "type
-                // outlives" error messages.
-                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-                let instantiated_predicates = self.fold_to_region_vid(instantiated_predicates);
-                self.normalize_and_prove_instantiated_predicates(
-                    instantiated_predicates,
+                self.fully_perform_op(
                     locations,
-                );
-
-                // In addition to proving the predicates, we have to
-                // prove that `ty` is well-formed -- this is because
-                // the WF of `ty` is predicated on the substs being
-                // well-formed, and we haven't proven *that*. We don't
-                // want to prove the WF of types from  `substs` directly because they
-                // haven't been normalized.
-                //
-                // FIXME(nmatsakis): Well, perhaps we should normalize
-                // them?  This would only be relevant if some input
-                // type were ill-formed but did not appear in `ty`,
-                // which...could happen with normalization...
-                self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+                    category,
+                    self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                        a, v, def_id, user_substs,
+                    )),
+                )?;
             }
         }
 
         Ok(())
     }
 
-    /// Replace all free regions in `value` with their NLL `RegionVid`
-    /// equivalents; if not in NLL, does nothing. This is never
-    /// particularly necessary -- we'll do it lazilly as we process
-    /// the value anyway -- but in some specific cases it is useful to
-    /// normalize so we can suppress duplicate error messages.
-    fn fold_to_region_vid<T>(&self, value: T) -> T
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        if let Some(borrowck_context) = &self.borrowck_context {
-            self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
-                if r.has_free_regions() {
-                    self.tcx().mk_region(ty::RegionKind::ReVar(
-                        borrowck_context.universal_regions.to_region_vid(r),
-                    ))
-                } else {
-                    r
-                }
-            })
-        } else {
-            value
-        }
-    }
-
     fn eq_opaque_type_and_type(
         &mut self,
         revealed_ty: Ty<'tcx>,