Repository: rust
Issue: Incremental compilation ICE with from compiler-state-dependent overflow errors 
Labels: I-ICE,A-trait-system,T-compiler,A-incr-comp,C-bug

So… here’s a bunch of traits and a deeply nested types
```rust
trait Tr<T: ?Sized> {}
impl Tr<()> for u8 {}
impl<Self_, T: ?Sized> Tr<S0<T>> for Self_ where Self_: Tr<T> {}

struct S0<T: ?Sized>(T);
type S1<T> = S0<S0<T>>;
type S2<T> = S1<S1<T>>;
type S3<T> = S2<S2<T>>;
type S4<T> = S3<S3<T>>;
type S5<T> = S4<S4<T>>;
type S6<T> = S5<S5<T>>;
// type S7<T> = S6<S6<T>>;
// update, for reproduction in 2023-09:
type S7<T> = S1<S2<S3<S4<S5<S6<T>>>>>>;
// (but compiler output below is not updated to mention newer Rust versions)

trait New<D> {}
impl<D: Copy, T: Tr<S7<()>>> New<D> for T {}
trait New2<D> {}
impl<D> New2<D> for u8 where u8: New<D> {}
```

and here’s a macro that helps us ask the compiler for trait implementations (thanks @digama0)
```rust
macro_rules! assert_impl {($ty:ty: $($trait:tt)*) => {
    const _: () = { fn f<T: $($trait)*>() {} fn g() { f::<$ty>() } };
}}
```

and if we ask the compiler
```rust
// asked directly this fails:
assert_impl!(u8: New2<()>);
```
then we’ll get an overflow error
```
error[E0275]: overflow evaluating the requirement `u8: Tr<S0<S0<()>>>`
  --> src/lib.rs:2:55
   |
2  |     const _: () = { fn f<T: $($trait)*>() {} fn g() { f::<$ty>() } };
   |                        - required by a bound in this  ^^^^^^^^
...
24 | assert_impl!(u8: New2<()>);
   | ---------------------------
   | |                |
   | |                required by this bound in `f`
   | in this macro invocation
   |
   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`small_pg`)
   = note: required because of the requirements on the impl of `Tr<S0<S0<S0<()>>>>` for `u8`
   = note: 125 redundant requirements hidden
   = note: required because of the requirements on the impl of `Tr<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<S0<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` for `u8`
note: required because of the requirements on the impl of `New<()>` for `u8`
  --> src/lib.rs:19:30
   |
19 | impl<D: Copy, T: Tr<S7<()>>> New<D> for T {}
   |                              ^^^^^^     ^
note: required because of the requirements on the impl of `New2<()>` for `u8`
  --> src/lib.rs:21:9
   |
21 | impl<D> New2<D> for u8 where u8: New<D> {}
   |         ^^^^^^^     ^^
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error
```

So far so good. But if we “first” ask about `u8: Tr<S7<()>>`, then the overflow error disappears:
```rust
// first ask
assert_impl!(u8: Tr<S7<()>>);

// then ask
assert_impl!(u8: New2<()>);
```

Of course the other way around, this still fails. Or instead of “of course it fails the other way around” let’s rather say: **This is pretty bad already** since the compilation success depends on the order in which two consts are defined. [Yes, `const`s, look into the definition of that macro ;-)]

Anyways. If we add a commented out version of the failing query above
```rust
// asked directly would fail:
// assert_impl!(u8: New2<()>);

// first ask
assert_impl!(u8: Tr<S7<()>>);

// then ask
assert_impl!(u8: New2<()>);
```
this compiles, and if you uncomment the commented out second line here without `cargo clean`ing your library, incremental compilation suddently becomes very ~~**excited**~~ _unhappy_.

```
    Checking small_pg v0.1.0 (/home/frank/Dokumente/playground/rust/small_pg)
thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Some(Fingerprint(16365582130792536210, 18134235757999171202))`,
 right: `Some(Fingerprint(8537439170242672706, 4648092694241280842))`: found unstable fingerprints for evaluate_obligation(1e88f23d10582546-8813245cfc000b69): Err(OverflowError)', /rustc/42816d61ead7e46d462df997958ccfd514f8c21c/compiler/rustc_query_system/src/query/plumbing.rs:593:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: rustc 1.53.0-nightly (42816d61e 2021-04-24) running on x86_64-unknown-linux-gnu

note: compiler flags: -C embed-bitcode=no -C debuginfo=2 -C incremental --crate-type lib

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `u8: New2<()>`
#1 [typeck] type-checking `_::g`
end of query stack
error: could not compile `small_pg`
```

<hr>

Detailed reproduction guide (*edit:* updated, 2023-09)
* use `nightly-2023-09-08`
* create a library crate containing [this code](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6777db26cc4358ff490a0111b7b22477)
* `cargo check`
* uncomment line 24, i.e. change line 24 to `assert_impl!(u8: New2<()>);`
* `cargo check` again

@rustbot label T-compiler A-incr-comp I-ICE