about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-31 15:13:05 +0000
committerbors <bors@rust-lang.org>2023-08-31 15:13:05 +0000
commit4b71f0303978581cb7444f0c493a0b35dab621e6 (patch)
tree3f4f171953be145b6830a2b93790a19f38a0b0d2
parentb30b535124aabf7835a09fe1c07e469711964011 (diff)
parent10ef8d9bf7b9acb921b335b48b9b7a3294fe178b (diff)
downloadrust-4b71f0303978581cb7444f0c493a0b35dab621e6.tar.gz
rust-4b71f0303978581cb7444f0c493a0b35dab621e6.zip
Auto merge of #115384 - lqd:default-universe-info, r=matthewjasper
Work around ICE in diagnostics for local super-universes missing `UniverseInfo`s

In issue #114907, canonicalization of liveness dropck-outlives results (IIUC) encounters universes absent from the original query.  Some local universes [are created](https://github.com/lqd/rust/blob/f3a1bae88c617330b8956818da3cea256336c1cf/compiler/rustc_infer/src/infer/canonical/query_response.rs#L417-L425) for the mapping, but importantly, they won't have associated causes.

These missing `UniverseInfo`s can be [needed](https://github.com/lqd/rust/blob/f3a1bae88c617330b8956818da3cea256336c1cf/compiler/rustc_borrowck/src/diagnostics/region_errors.rs#L376) during diagnostics, [causing the `IndexMap: key not found` ICE](https://github.com/lqd/rust/blob/d55522aad87c5605d7edd5dd4b37926e8b446117/compiler/rustc_borrowck/src/region_infer/mod.rs#L2252) seen in the issue.

This PR works around this by returning the suboptimal catch-all cause, to avoid the ICE. It does results in suboptimal diagnostics right now, but it's better than an ICE.

r? `@matthewjasper.`

Let me know if there's a good easy-ish way to fix this, but I believe that for some of these erroneous cases and diagnostics, that inference/canonicalization/higher-ranked subtyping/etc may not behave exactly the same with the new trait solver? If that's the case then it'd probably be best to wait a bit more to do the correct fix.

Fixes #114907.

cc `@aliemjay`
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs19
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.rs40
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.stderr79
5 files changed, 132 insertions, 19 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index b8cd94e5422..1049e7a8bbe 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -2249,7 +2249,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        self.universe_causes[&universe].clone()
+        // Query canonicalization can create local superuniverses (for example in
+        // `InferCtx::query_response_substitution_guess`), but they don't have an associated
+        // `UniverseInfo` explaining why they were created.
+        // This can cause ICEs if these causes are accessed in diagnostics, for example in issue
+        // #114907 where this happens via liveness and dropck outlives results.
+        // Therefore, we return a default value in case that happens, which should at worst emit a
+        // suboptimal error, instead of the ICE.
+        self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other())
     }
 
     /// Tries to find the terminator of the loop in which the region 'r' resides.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 16f5e68a06f..b7adc314f07 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -9,7 +9,7 @@ use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
 use rustc_trait_selection::traits::ObligationCause;
 
-use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
+use crate::diagnostics::ToUniverseInfo;
 
 use super::{Locations, NormalizeLocation, TypeChecker};
 
@@ -46,13 +46,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             self.push_region_constraints(locations, category, data);
         }
 
+        // If the query has created new universes and errors are going to be emitted, register the
+        // cause of these new universes for improved diagnostics.
         let universe = self.infcx.universe();
-
-        if old_universe != universe {
-            let universe_info = match error_info {
-                Some(error_info) => error_info.to_universe_info(old_universe),
-                None => UniverseInfo::other(),
-            };
+        if old_universe != universe && let Some(error_info) = error_info {
+            let universe_info = error_info.to_universe_info(old_universe);
             for u in (old_universe + 1)..=universe {
                 self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
             }
@@ -69,15 +67,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        let old_universe = self.infcx.universe();
-
         let (instantiated, _) =
             self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
-
-        for u in (old_universe + 1)..=self.infcx.universe() {
-            self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
-        }
-
         instantiated
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3004291c3e7..28286243e82 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -163,10 +163,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
 
     debug!(?normalized_inputs_and_output);
 
-    for u in ty::UniverseIndex::ROOT..=infcx.universe() {
-        constraints.universe_causes.insert(u, UniverseInfo::other());
-    }
-
     let mut borrowck_context = BorrowCheckContext {
         universal_regions,
         location_table,
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.rs b/tests/ui/nll/missing-universe-cause-issue-114907.rs
new file mode 100644
index 00000000000..94acdccfcf2
--- /dev/null
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.rs
@@ -0,0 +1,40 @@
+// This is a non-regression test for issue #114907 where an ICE happened because of missing
+// `UniverseInfo`s accessed during diagnostics.
+//
+// A couple notes:
+// - the `FnOnce` bounds need an arg that is a reference
+// - a custom `Drop` is needed somewhere in the type that `accept` returns, to create universes
+//   during liveness and dropck outlives computation
+
+// check-fail
+
+trait Role {
+    type Inner;
+}
+
+struct HandshakeCallback<C>(C);
+impl<C: FnOnce(&())> Role for HandshakeCallback<C> {
+    type Inner = ();
+}
+
+struct Handshake<R: Role> {
+    _inner: Option<R::Inner>,
+}
+impl<R: Role> Drop for Handshake<R> {
+    fn drop(&mut self) {}
+}
+
+fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
+    todo!()
+}
+
+fn main() {
+    let callback = |_| {};
+    accept(callback);
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR higher-ranked subtype error
+    //~| ERROR higher-ranked subtype error
+}
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
new file mode 100644
index 00000000000..c3dd4257a73
--- /dev/null
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
@@ -0,0 +1,79 @@
+error[E0308]: mismatched types
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:5
+   |
+LL |     accept(callback);
+   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected trait `for<'a> FnOnce<(&'a (),)>`
+              found trait `FnOnce<(&(),)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/missing-universe-cause-issue-114907.rs:32:20
+   |
+LL |     let callback = |_| {};
+   |                    ^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/missing-universe-cause-issue-114907.rs:27:14
+   |
+LL | fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
+   |              ^^^^^^^^^^^
+help: consider specifying the type of the closure parameters
+   |
+LL |     let callback = |_: &_| {};
+   |                    ~~~~~~~
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:5
+   |
+LL |     accept(callback);
+   |     ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:5
+   |
+LL |     accept(callback);
+   |     ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
+
+error[E0308]: mismatched types
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:5
+   |
+LL |     accept(callback);
+   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected trait `for<'a> FnOnce<(&'a (),)>`
+              found trait `FnOnce<(&(),)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/missing-universe-cause-issue-114907.rs:32:20
+   |
+LL |     let callback = |_| {};
+   |                    ^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/missing-universe-cause-issue-114907.rs:20:21
+   |
+LL | struct Handshake<R: Role> {
+   |                     ^^^^
+help: consider specifying the type of the closure parameters
+   |
+LL |     let callback = |_: &_| {};
+   |                    ~~~~~~~
+
+error: higher-ranked subtype error
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:21
+   |
+LL |     accept(callback);
+   |                     ^
+
+error: higher-ranked subtype error
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:21
+   |
+LL |     accept(callback);
+   |                     ^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.