Skip to content

Commit 4b71f03

Browse files
committed
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`
2 parents b30b535 + 10ef8d9 commit 4b71f03

File tree

5 files changed

+132
-19
lines changed

5 files changed

+132
-19
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -2249,7 +2249,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
22492249
}
22502250

22512251
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
2252-
self.universe_causes[&universe].clone()
2252+
// Query canonicalization can create local superuniverses (for example in
2253+
// `InferCtx::query_response_substitution_guess`), but they don't have an associated
2254+
// `UniverseInfo` explaining why they were created.
2255+
// This can cause ICEs if these causes are accessed in diagnostics, for example in issue
2256+
// #114907 where this happens via liveness and dropck outlives results.
2257+
// Therefore, we return a default value in case that happens, which should at worst emit a
2258+
// suboptimal error, instead of the ICE.
2259+
self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other())
22532260
}
22542261

22552262
/// Tries to find the terminator of the loop in which the region 'r' resides.

compiler/rustc_borrowck/src/type_check/canonical.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_span::Span;
99
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
1010
use rustc_trait_selection::traits::ObligationCause;
1111

12-
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
12+
use crate::diagnostics::ToUniverseInfo;
1313

1414
use super::{Locations, NormalizeLocation, TypeChecker};
1515

@@ -46,13 +46,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
4646
self.push_region_constraints(locations, category, data);
4747
}
4848

49+
// If the query has created new universes and errors are going to be emitted, register the
50+
// cause of these new universes for improved diagnostics.
4951
let universe = self.infcx.universe();
50-
51-
if old_universe != universe {
52-
let universe_info = match error_info {
53-
Some(error_info) => error_info.to_universe_info(old_universe),
54-
None => UniverseInfo::other(),
55-
};
52+
if old_universe != universe && let Some(error_info) = error_info {
53+
let universe_info = error_info.to_universe_info(old_universe);
5654
for u in (old_universe + 1)..=universe {
5755
self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
5856
}
@@ -69,15 +67,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
6967
where
7068
T: TypeFoldable<TyCtxt<'tcx>>,
7169
{
72-
let old_universe = self.infcx.universe();
73-
7470
let (instantiated, _) =
7571
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
76-
77-
for u in (old_universe + 1)..=self.infcx.universe() {
78-
self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
79-
}
80-
8172
instantiated
8273
}
8374

compiler/rustc_borrowck/src/type_check/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
163163

164164
debug!(?normalized_inputs_and_output);
165165

166-
for u in ty::UniverseIndex::ROOT..=infcx.universe() {
167-
constraints.universe_causes.insert(u, UniverseInfo::other());
168-
}
169-
170166
let mut borrowck_context = BorrowCheckContext {
171167
universal_regions,
172168
location_table,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// This is a non-regression test for issue #114907 where an ICE happened because of missing
2+
// `UniverseInfo`s accessed during diagnostics.
3+
//
4+
// A couple notes:
5+
// - the `FnOnce` bounds need an arg that is a reference
6+
// - a custom `Drop` is needed somewhere in the type that `accept` returns, to create universes
7+
// during liveness and dropck outlives computation
8+
9+
// check-fail
10+
11+
trait Role {
12+
type Inner;
13+
}
14+
15+
struct HandshakeCallback<C>(C);
16+
impl<C: FnOnce(&())> Role for HandshakeCallback<C> {
17+
type Inner = ();
18+
}
19+
20+
struct Handshake<R: Role> {
21+
_inner: Option<R::Inner>,
22+
}
23+
impl<R: Role> Drop for Handshake<R> {
24+
fn drop(&mut self) {}
25+
}
26+
27+
fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
28+
todo!()
29+
}
30+
31+
fn main() {
32+
let callback = |_| {};
33+
accept(callback);
34+
//~^ ERROR mismatched types
35+
//~| ERROR mismatched types
36+
//~| ERROR implementation of `FnOnce` is not general enough
37+
//~| ERROR implementation of `FnOnce` is not general enough
38+
//~| ERROR higher-ranked subtype error
39+
//~| ERROR higher-ranked subtype error
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/missing-universe-cause-issue-114907.rs:33:5
3+
|
4+
LL | accept(callback);
5+
| ^^^^^^^^^^^^^^^^ one type is more general than the other
6+
|
7+
= note: expected trait `for<'a> FnOnce<(&'a (),)>`
8+
found trait `FnOnce<(&(),)>`
9+
note: this closure does not fulfill the lifetime requirements
10+
--> $DIR/missing-universe-cause-issue-114907.rs:32:20
11+
|
12+
LL | let callback = |_| {};
13+
| ^^^
14+
note: the lifetime requirement is introduced here
15+
--> $DIR/missing-universe-cause-issue-114907.rs:27:14
16+
|
17+
LL | fn accept<C: FnOnce(&())>(_: C) -> Handshake<HandshakeCallback<C>> {
18+
| ^^^^^^^^^^^
19+
help: consider specifying the type of the closure parameters
20+
|
21+
LL | let callback = |_: &_| {};
22+
| ~~~~~~~
23+
24+
error: implementation of `FnOnce` is not general enough
25+
--> $DIR/missing-universe-cause-issue-114907.rs:33:5
26+
|
27+
LL | accept(callback);
28+
| ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
29+
|
30+
= note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
31+
= note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
32+
33+
error: implementation of `FnOnce` is not general enough
34+
--> $DIR/missing-universe-cause-issue-114907.rs:33:5
35+
|
36+
LL | accept(callback);
37+
| ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
38+
|
39+
= note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
40+
= note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
41+
42+
error[E0308]: mismatched types
43+
--> $DIR/missing-universe-cause-issue-114907.rs:33:5
44+
|
45+
LL | accept(callback);
46+
| ^^^^^^^^^^^^^^^^ one type is more general than the other
47+
|
48+
= note: expected trait `for<'a> FnOnce<(&'a (),)>`
49+
found trait `FnOnce<(&(),)>`
50+
note: this closure does not fulfill the lifetime requirements
51+
--> $DIR/missing-universe-cause-issue-114907.rs:32:20
52+
|
53+
LL | let callback = |_| {};
54+
| ^^^
55+
note: the lifetime requirement is introduced here
56+
--> $DIR/missing-universe-cause-issue-114907.rs:20:21
57+
|
58+
LL | struct Handshake<R: Role> {
59+
| ^^^^
60+
help: consider specifying the type of the closure parameters
61+
|
62+
LL | let callback = |_: &_| {};
63+
| ~~~~~~~
64+
65+
error: higher-ranked subtype error
66+
--> $DIR/missing-universe-cause-issue-114907.rs:33:21
67+
|
68+
LL | accept(callback);
69+
| ^
70+
71+
error: higher-ranked subtype error
72+
--> $DIR/missing-universe-cause-issue-114907.rs:33:21
73+
|
74+
LL | accept(callback);
75+
| ^
76+
77+
error: aborting due to 6 previous errors
78+
79+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)