about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-11-29 08:06:42 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-19 03:29:29 -0500
commit514dfdbf12b71758c7abc3219ae1a3936e4d59d9 (patch)
treeedfa206f39fb3f125496685fb173809c4b1633d2
parent6bdce25e155d846bb9252fa4a18baef7e74cf8bf (diff)
downloadrust-514dfdbf12b71758c7abc3219ae1a3936e4d59d9.tar.gz
rust-514dfdbf12b71758c7abc3219ae1a3936e4d59d9.zip
Add tests for sub relationship on free/bound regions, revealing a bug.
-rw-r--r--src/librustc_driver/test.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 508af4c28e6..943650ce8a6 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -25,6 +25,7 @@ use rustc_typeck::middle::infer::combine::Combine;
 use rustc_typeck::middle::infer;
 use rustc_typeck::middle::infer::lub::Lub;
 use rustc_typeck::middle::infer::glb::Glb;
+use rustc_typeck::middle::infer::sub::Sub;
 use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString};
 use rustc::session::{mod,config};
 use syntax::{abi, ast, ast_map, ast_util};
@@ -341,6 +342,11 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         infer::TypeTrace::dummy()
     }
 
+    pub fn sub(&self) -> Sub<'a, 'tcx> {
+        let trace = self.dummy_type_trace();
+        Sub(self.infcx.combine_fields(true, trace))
+    }
+
     pub fn lub(&self) -> Lub<'a, 'tcx> {
         let trace = self.dummy_type_trace();
         Lub(self.infcx.combine_fields(true, trace))
@@ -359,6 +365,33 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         }
     }
 
+    /// Checks that `t1 <: t2` is true (this may register additional
+    /// region checks).
+    pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
+        match self.sub().tys(t1, t2) {
+            Ok(_) => { }
+            Err(ref e) => {
+                panic!("unexpected error computing sub({},{}): {}",
+                       t1.repr(self.infcx.tcx),
+                       t2.repr(self.infcx.tcx),
+                       ty::type_err_to_str(self.infcx.tcx, e));
+            }
+        }
+    }
+
+    /// Checks that `t1 <: t2` is false (this may register additional
+    /// region checks).
+    pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
+        match self.sub().tys(t1, t2) {
+            Err(_) => { }
+            Ok(_) => {
+                panic!("unexpected success computing sub({},{})",
+                       t1.repr(self.infcx.tcx),
+                       t2.repr(self.infcx.tcx));
+            }
+        }
+    }
+
     /// Checks that `LUB(t1,t2) == t_lub`
     pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) {
         match self.lub().tys(t1, t2) {
@@ -422,6 +455,54 @@ fn contravariant_region_ptr_err() {
 }
 
 #[test]
+fn sub_free_bound_false() {
+    //! Test that:
+    //!
+    //!     fn(&'a int) <: for<'b> fn(&'b int)
+    //!
+    //! does NOT hold.
+
+    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
+        let t_rptr_free1 = env.t_rptr_free(0, 1);
+        let t_rptr_bound1 = env.t_rptr_late_bound(1);
+        env.check_not_sub(env.t_fn(&[t_rptr_free1], ty::mk_int()),
+                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+    })
+}
+
+#[test]
+fn sub_bound_free_true() {
+    //! Test that:
+    //!
+    //!     for<'a> fn(&'a int) <: fn(&'b int)
+    //!
+    //! DOES hold.
+
+    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
+        let t_rptr_bound1 = env.t_rptr_late_bound(1);
+        let t_rptr_free1 = env.t_rptr_free(0, 1);
+        env.check_sub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
+                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+    })
+}
+
+#[test]
+fn sub_free_bound_false_infer() {
+    //! Test that:
+    //!
+    //!     fn(_#1) <: for<'b> fn(&'b int)
+    //!
+    //! does NOT hold for any instantiation of `_#1`.
+
+    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
+        let t_infer1 = env.infcx.next_ty_var();
+        let t_rptr_bound1 = env.t_rptr_late_bound(1);
+        env.check_not_sub(env.t_fn(&[t_infer1], ty::mk_int()),
+                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+    })
+}
+
+#[test]
 fn lub_bound_bound() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);