rust-lang / rust-lang/rust

Circularly defined GAT is somehow allowed and ICEs Miri

Open
#149,898 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-associated-items A-GATs A-mir-opt A-miri A-trait-system C-bug I-ICE T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

trait NotImplemented {}

trait Trait {
    type Assoc<T: Trait>: NotImplemented;
}

struct Thing;
impl Trait for Thing {
    type Assoc<T: Trait> = T::Assoc<T>;
}

fn foo<T: Trait>() {
    let _: Option<&<T as Trait>::Assoc<T>> = None;
}

fn main() {
    foo::<Thing>();
}

This code probably shouldn't compile, since <Thing as Trait>::Assoc<Thing> is circularly defined. Instead, it compiles and runs without errors.

Running this code with Miri gives the following ICE:

ICE with Miri
error[E0275]: overflow evaluating the requirement `<Thing as Trait>::Assoc<Thing> == _`


Miri caused an ICE during evaluation. Here's the interpreter backtrace at the time of the panic:
note: the place in the program where the ICE was triggered
  --> src/main.rs:13:46
   |
13 |     let _: Option<&<T as Trait>::Assoc<T>> = None;
   |                                              ^^^^
   |
   = note: BACKTRACE:
   = note: inside `foo::<Thing>` at src/main.rs:13:46: 13:50
note: inside `main`
  --> src/main.rs:17:5
   |
17 |     foo::<Thing>();
   |     ^^^^^^^^^^^^^^
   = note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
   = note: inside `std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:160:18: 160:21
   = note: inside closure at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:206:18: 206:75
   = note: inside `std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:287:13: 287:31
   = note: inside `std::panicking::catch_unwind::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panicking.rs:581:40: 581:43
   = note: inside `std::panicking::catch_unwind::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panicking.rs:544:19: 544:88
   = note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panic.rs:359:14: 359:40
   = note: inside closure at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:175:24: 175:49
   = note: inside `std::panicking::catch_unwind::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panicking.rs:581:40: 581:43
   = note: inside `std::panicking::catch_unwind::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panicking.rs:544:19: 544:88
   = note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panic.rs:359:14: 359:40
   = note: inside `std::rt::lang_start_internal` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:171:5: 193:7
   = note: inside `std::rt::lang_start::<()>` at /Users/timch/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:205:5: 210:6

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0275`.

Additionally, compiling the code with -Zmir-opt-level=1 works without errors. However, compiling with -Zmir-opt-level=0 gives the following error:

Error with -Zmir-opt-level=0
error[E0275]: overflow evaluating the requirement `<Thing as Trait>::Assoc<Thing> == _`

For more information about this error, try `rustc --explain E0275`.
error: could not compile `foo` (bin "foo") due to 1 previous error

Also, changing the let _ into let _x gives the following error when compiled normally (identical to the above error):

Error with let _x
error[E0275]: overflow evaluating the requirement `<Thing as Trait>::Assoc<Thing> == _`

For more information about this error, try `rustc --explain E0275`.
error: could not compile `foo` (bin "foo") due to 1 previous error

Changing the code to let _x and also using cargo check instead of cargo build makes the code compile again.

Possibly related to #135246, #135011, and #115175

Meta

rustc --version --verbose:

rustc 1.94.0-nightly (f52090008 2025-12-10)
binary: rustc
commit-hash: f5209000832c9d3bc29c91f4daef4ca9f28dc797
commit-date: 2025-12-10
host: aarch64-apple-darwin
release: 1.94.0-nightly
LLVM version: 21.1.5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the example from src/main.rs with rustc, Miri, cargo build, cargo check, and the reported -Zmir-opt-level settings. Compare the circular associated-type diagnostic and Miri behavior across those paths; done means the invalid circular definition is rejected consistently without an ICE.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.