]> git.lizzy.rs Git - rust.git/commitdiff
fix universes in the NLL type tests
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 15 Jun 2022 21:28:05 +0000 (17:28 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 15 Jun 2022 21:28:05 +0000 (17:28 -0400)
In the NLL code, we were not accommodating universes in the
`type_test` logic. This led to issue 98095.

compiler/rustc_borrowck/src/region_infer/mod.rs
src/test/ui/nll/type-test-universe.rs [new file with mode: 0644]
src/test/ui/nll/type-test-universe.stderr [new file with mode: 0644]

index d553a60faef0d9a22876110232458249ae5951e7..4830eb3f464a7a5d4683bbcca3127b7843195743 100644 (file)
@@ -1342,6 +1342,18 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
         let sub_region_scc = self.constraint_sccs.scc(sub_region);
         let sup_region_scc = self.constraint_sccs.scc(sup_region);
 
+        // If we are checking that `'sup: 'sub`, and `'sub` contains
+        // some placeholder that `'sup` cannot name, then this is only
+        // true if `'sup` outlives static.
+        if !self.universe_compatible(sub_region_scc, sup_region_scc) {
+            debug!(
+                "eval_outlives: sub universe `{sub_region_scc:?}` is not nameable \
+                by super `{sup_region_scc:?}`, promoting to static",
+            );
+
+            return self.eval_outlives(sup_region, self.universal_regions.fr_static);
+        }
+
         // Both the `sub_region` and `sup_region` consist of the union
         // of some number of universal regions (along with the union
         // of various points in the CFG; ignore those points for
@@ -1356,6 +1368,9 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
             });
 
         if !universal_outlives {
+            debug!(
+                "eval_outlives: returning false because sub region contains a universal region not present in super"
+            );
             return false;
         }
 
@@ -1364,10 +1379,18 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
 
         if self.universal_regions.is_universal_region(sup_region) {
             // Micro-opt: universal regions contain all points.
+            debug!(
+                "eval_outlives: returning true because super is universal and hence contains all points"
+            );
             return true;
         }
 
-        self.scc_values.contains_points(sup_region_scc, sub_region_scc)
+        let result = self.scc_values.contains_points(sup_region_scc, sub_region_scc);
+        debug!(
+            "eval_outlives: returning {} because of comparison between points in sup/sub",
+            result
+        );
+        result
     }
 
     /// Once regions have been propagated, this method is used to see
diff --git a/src/test/ui/nll/type-test-universe.rs b/src/test/ui/nll/type-test-universe.rs
new file mode 100644 (file)
index 0000000..f9801c0
--- /dev/null
@@ -0,0 +1,21 @@
+// Regression test for #98095: make sure that
+// we detect that S needs to outlive 'static.
+
+fn outlives_forall<T>()
+where
+    for<'u> T: 'u,
+{
+}
+
+fn test1<S>() {
+    outlives_forall::<S>();
+    //~^ ERROR `S` does not live long enough
+}
+
+struct Value<'a>(&'a ());
+fn test2<'a>() {
+    outlives_forall::<Value<'a>>();
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/type-test-universe.stderr b/src/test/ui/nll/type-test-universe.stderr
new file mode 100644 (file)
index 0000000..242486c
--- /dev/null
@@ -0,0 +1,16 @@
+error: `S` does not live long enough
+  --> $DIR/type-test-universe.rs:11:5
+   |
+LL |     outlives_forall::<S>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: lifetime may not live long enough
+  --> $DIR/type-test-universe.rs:17:5
+   |
+LL | fn test2<'a>() {
+   |          -- lifetime `'a` defined here
+LL |     outlives_forall::<Value<'a>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+