]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/infer/at.rs
port the relate-types code from NLL type-check into a type-op
[rust.git] / src / librustc / infer / at.rs
index 756e0b5f9fb6a00cf47c84f26830e8a72ccf9f83..0e4c94aaaf3942e31755f00f6eb8d13b90e23491 100644 (file)
@@ -40,9 +40,9 @@
 use ty::relate::{Relate, TypeRelation};
 
 pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> {
-    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    cause: &'a ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    pub cause: &'a ObligationCause<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
 }
 
 pub struct Trace<'a, 'gcx: 'tcx, 'tcx: 'a> {
@@ -142,6 +142,28 @@ pub fn eq<T>(self,
         self.trace(expected, actual).eq(&expected, &actual)
     }
 
+    pub fn relate<T>(
+        self,
+        expected: T,
+        variance: ty::Variance,
+        actual: T,
+    ) -> InferResult<'tcx, ()>
+        where T: ToTrace<'tcx>
+    {
+        match variance {
+            ty::Variance::Covariant => self.sub(expected, actual),
+            ty::Variance::Invariant => self.eq(expected, actual),
+            ty::Variance::Contravariant => self.sup(expected, actual),
+
+            // We could make this make sense but it's not readily
+            // exposed and I don't feel like dealing with it. Note
+            // that bivariance in general does a bit more than just
+            // *nothing*, it checks that the types are the same
+            // "modulo variance" basically.
+            ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
+        }
+    }
+
     /// Compute the least-upper-bound, or mutual supertype, of two
     /// values. The order of the arguments doesn't matter, but since
     /// this can result in an error (e.g., if asked to compute LUB of
@@ -169,7 +191,7 @@ pub fn glb<T>(self,
     }
 
     /// Sets the "trace" values that will be used for
-    /// error-repporting, but doesn't actually perform any operation
+    /// error-reporting, but doesn't actually perform any operation
     /// yet (this is useful when you want to set the trace using
     /// distinct values from those you wish to operate upon).
     pub fn trace<T>(self,
@@ -281,6 +303,20 @@ fn to_trace(cause: &ObligationCause<'tcx>,
     }
 }
 
+impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
+    fn to_trace(cause: &ObligationCause<'tcx>,
+                a_is_expected: bool,
+                a: Self,
+                b: Self)
+                -> TypeTrace<'tcx>
+    {
+        TypeTrace {
+            cause: cause.clone(),
+            values: Regions(ExpectedFound::new(a_is_expected, a, b))
+        }
+    }
+}
+
 impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
     fn to_trace(cause: &ObligationCause<'tcx>,
                 a_is_expected: bool,