Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work around ICE in diagnostics for local super-universes missing UniverseInfos #115384

Merged
merged 5 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to do this here we should remove the places where we add UniverseInfo::other to universe causes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed a few commits to remove these. I think that's all of them.

}

/// Tries to find the terminator of the loop in which the region 'r' resides.
Expand Down
19 changes: 5 additions & 14 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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());
}
Expand All @@ -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
}

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/nll/missing-universe-cause-issue-114907.rs
Original file line number Diff line number Diff line change
@@ -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
}
79 changes: 79 additions & 0 deletions tests/ui/nll/missing-universe-cause-issue-114907.stderr
Original file line number Diff line number Diff line change
@@ -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`.