about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-17 14:55:42 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-10-19 09:32:30 -0400
commitf99300fcbdfec2908aeb93c823fc37f92a4d2d30 (patch)
treed20774e43c5a4465a27a1e62a396a0fb535edfb8 /src
parente7ab33e7a61ff046f1736f1b027c16d9494e20b8 (diff)
downloadrust-f99300fcbdfec2908aeb93c823fc37f92a4d2d30.tar.gz
rust-f99300fcbdfec2908aeb93c823fc37f92a4d2d30.zip
pull `relate_type_and_user_type` code into `type_check` module
It's really layered atop the core "relate-types" code
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs111
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs120
2 files changed, 99 insertions, 132 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 11ea46fdef2..823a249760f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts, UserSelfTy};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -901,23 +901,37 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn sub_types(
+    /// Convenient wrapper around `relate_tys::relate_types` -- see
+    /// that fn for docs.
+    fn relate_types(
         &mut self,
-        sub: Ty<'tcx>,
-        sup: Ty<'tcx>,
+        a: Ty<'tcx>,
+        v: ty::Variance,
+        b: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
-        relate_tys::sub_types(
+        relate_tys::relate_types(
             self.infcx,
-            sub,
-            sup,
+            a,
+            v,
+            b,
             locations,
             category,
             self.borrowck_context.as_mut().map(|x| &mut **x),
         )
     }
 
+    fn sub_types(
+        &mut self,
+        sub: Ty<'tcx>,
+        sup: Ty<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) -> Fallible<()> {
+        self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
+    }
+
     /// Try to relate `sub <: sup`; if this fails, instantiate opaque
     /// variables in `sub` with their inferred definitions and try
     /// again. This is used for opaque types in places (e.g., `let x:
@@ -950,34 +964,79 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
-        relate_tys::eq_types(
-            self.infcx,
-            a,
-            b,
-            locations,
-            category,
-            self.borrowck_context.as_mut().map(|x| &mut **x),
-        )
+        self.relate_types(a, ty::Variance::Invariant, b, locations, category)
     }
 
     fn relate_type_and_user_type(
         &mut self,
         a: Ty<'tcx>,
         v: ty::Variance,
-        b: UserTypeAnnotation<'tcx>,
+        user_ty: UserTypeAnnotation<'tcx>,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
-        let ty = relate_tys::relate_type_and_user_type(
-            self.infcx,
-            a,
-            v,
-            b,
-            locations,
-            category,
-            self.borrowck_context.as_mut().map(|x| &mut **x),
-        )?;
-        self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+        let tcx = self.tcx();
+
+        debug!(
+            "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, 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)?;
+
+                self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+            }
+            UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
+                let (
+                    UserSubsts {
+                        substs,
+                        user_self_ty,
+                    },
+                    _,
+                ) = 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);
+
+                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);
+
+                    // 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(ty), locations, category);
+            }
+        }
+
         Ok(())
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index 665ed24ac3d..13ebf46bdb1 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -12,35 +12,23 @@ use borrow_check::nll::constraints::OutlivesConstraint;
 use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
 use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
-use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
+use rustc::mir::ConstraintCategory;
 use rustc::traits::query::Fallible;
 use rustc::ty::relate::TypeRelation;
-use rustc::ty::subst::{Subst, UserSelfTy, UserSubsts};
-use rustc::ty::{self, Ty, TypeFoldable};
-use syntax_pos::DUMMY_SP;
-
-/// Adds sufficient constraints to ensure that `a <: b`.
-pub(super) fn sub_types<'tcx>(
-    infcx: &InferCtxt<'_, '_, 'tcx>,
-    a: Ty<'tcx>,
-    b: Ty<'tcx>,
-    locations: Locations,
-    category: ConstraintCategory,
-    borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
-) -> Fallible<()> {
-    debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
-    TypeRelating::new(
-        infcx,
-        NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
-        ty::Variance::Covariant,
-    ).relate(&a, &b)?;
-    Ok(())
-}
-
-/// Adds sufficient constraints to ensure that `a == b`.
-pub(super) fn eq_types<'tcx>(
+use rustc::ty::{self, Ty};
+
+/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
+///
+/// - "Covariant" `a <: b`
+/// - "Invariant" `a == b`
+/// - "Contravariant" `a :> b`
+///
+/// NB. The type `a` is permitted to have unresolved inference
+/// variables, but not the type `b`.
+pub(super) fn relate_types<'tcx>(
     infcx: &InferCtxt<'_, '_, 'tcx>,
     a: Ty<'tcx>,
+    v: ty::Variance,
     b: Ty<'tcx>,
     locations: Locations,
     category: ConstraintCategory,
@@ -50,91 +38,11 @@ pub(super) fn eq_types<'tcx>(
     TypeRelating::new(
         infcx,
         NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
-        ty::Variance::Invariant,
+        v,
     ).relate(&a, &b)?;
     Ok(())
 }
 
-/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
-/// a user-given type (which means it may have canonical variables
-/// encoding things like `_`).
-pub(super) fn relate_type_and_user_type<'tcx>(
-    infcx: &InferCtxt<'_, '_, 'tcx>,
-    a: Ty<'tcx>,
-    v: ty::Variance,
-    user_ty: UserTypeAnnotation<'tcx>,
-    locations: Locations,
-    category: ConstraintCategory,
-    borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
-) -> Fallible<Ty<'tcx>> {
-    debug!(
-        "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
-        a, v, user_ty, locations
-    );
-
-    // The `TypeRelating` code assumes that the "canonical variables"
-    // appear in the "a" side, so flip `Contravariant` ambient
-    // variance to get the right relationship.
-    let v1 = ty::Contravariant.xform(v);
-
-    let mut type_relating = TypeRelating::new(
-        infcx,
-        NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
-        v1,
-    );
-
-    match user_ty {
-        UserTypeAnnotation::Ty(canonical_ty) => {
-            let (ty, _) =
-                infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
-            type_relating.relate(&ty, &a)?;
-            Ok(ty)
-        }
-        UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
-            let (
-                UserSubsts {
-                    substs,
-                    user_self_ty,
-                },
-                _,
-            ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
-
-            let ty = infcx.tcx.type_of(def_id);
-            let ty = ty.subst(infcx.tcx, substs);
-
-            type_relating.relate(&ty, &a)?;
-
-            if let Some(UserSelfTy {
-                impl_def_id,
-                self_ty,
-            }) = user_self_ty
-            {
-                let impl_self_ty = infcx.tcx.type_of(impl_def_id);
-                let impl_self_ty = impl_self_ty.subst(infcx.tcx, &substs);
-
-                // 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 = infcx.resolve_type_vars_if_possible(&impl_self_ty);
-                assert!(!impl_self_ty.has_infer_types());
-
-                type_relating.relate_with_variance(
-                    ty::Variance::Invariant,
-                    &self_ty,
-                    &impl_self_ty,
-                )?;
-            }
-
-            Ok(ty)
-        }
-    }
-}
-
 struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'gcx: 'tcx, 'tcx: 'bccx> {
     infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
     borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,