Skip to content

Incremental compilation ICE with from compiler-state-dependent overflow errors  #84963

Open
@steffahn

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, consts, 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 cleaning 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-incr-compArea: Incremental compilationA-trait-systemArea: Trait systemC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions