From 12912b9cde4791dead52e49ae87f80c579bc0cd5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Jun 2022 17:28:05 -0400 Subject: [PATCH] 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. --- .../rustc_borrowck/src/region_infer/mod.rs | 25 ++++++++++++++++++- src/test/ui/nll/type-test-universe.rs | 21 ++++++++++++++++ src/test/ui/nll/type-test-universe.stderr | 16 ++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/nll/type-test-universe.rs create mode 100644 src/test/ui/nll/type-test-universe.stderr 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() +where + for<'u> T: 'u, +{ +} + +fn test1() { + outlives_forall::(); + //~^ ERROR `S` does not live long enough +} + +struct Value<'a>(&'a ()); +fn test2<'a>() { + outlives_forall::>(); + //~^ 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::(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +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::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors +