about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2022-06-15 17:28:05 -0400
committerNiko Matsakis <niko@alum.mit.edu>2022-06-15 17:28:05 -0400
commit12912b9cde4791dead52e49ae87f80c579bc0cd5 (patch)
tree459be02e20d5f3c3c4aa20d3a72e94ef5ff96f6d
parentb7b3d2cee0e371fdecf9726ab949a24ead3dcb97 (diff)
downloadrust-12912b9cde4791dead52e49ae87f80c579bc0cd5.tar.gz
rust-12912b9cde4791dead52e49ae87f80c579bc0cd5.zip
fix universes in the NLL type tests
In the NLL code, we were not accommodating universes in the
`type_test` logic. This led to issue 98095.
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs25
-rw-r--r--src/test/ui/nll/type-test-universe.rs21
-rw-r--r--src/test/ui/nll/type-test-universe.stderr16
3 files changed, 61 insertions, 1 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d553a60faef..4830eb3f464 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1342,6 +1342,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         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 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             });
 
         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 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         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
index 00000000000..f9801c07d7b
--- /dev/null
+++ b/src/test/ui/nll/type-test-universe.rs
@@ -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
index 00000000000..242486c360a
--- /dev/null
+++ b/src/test/ui/nll/type-test-universe.stderr
@@ -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
+