Incremental compilation ICE with from compiler-state-dependent overflow errors #84963
Description
So… here’s a bunch of traits and a deeply nested types
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)
macro_rules! assert_impl {($ty:ty: $($trait:tt)*) => {
const _: () = { fn f<T: $($trait)*>() {} fn g() { f::<$ty>() } };
}}
and if we ask the compiler
// 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:
// 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
// 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`
Detailed reproduction guide (edit: updated, 2023-09)
- use
nightly-2023-09-08
- create a library crate containing this code
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
Activity