Skip to content

fix: Panic when trait solver re-enters itself - #23367

Merged
ChayimFriedman2 merged 1 commit into
rust-lang:masterfrom
Wilfred:panic_on_solver_reentry
Sep 15, 2026
Merged

ChayimFriedman2 merged 1 commit into
rust-lang:masterfrom
Wilfred:panic_on_solver_reentry

Conversation

@Wilfred

@Wilfred Wilfred commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

rust-analyzer would panic when the trait solver called itself, which can happen during const evaluation.

rustc has the same function, but doesn't panic, so just copy the rustc implementation:

https://github.com/rust-lang/rust/blob/5392d2f545c6836dc79f209bcc14ac7179dbc4f2/compiler/rustc_middle/src/ty/context/impl_interner.rs#L155

This caused SCIP crashes on the dudykr/stc, renegade-fi/renegade, and tikv/tikv GitHub repositories, so would presumably cause LSP crashes too.

The linked trait-system-refactor-initiative issue has a repro, but for reference I minimised a repro independently:

trait Tr { const N: usize; }
struct A<const N: usize>;
impl<const N: usize> Tr for A<N> { const N: usize = N; }
const fn k<T: Tr>() -> usize { T::N }
struct B<const N: usize>;
impl<const N: usize> Tr for B<N> where A<{ k::<A<3>>() }>: Tr { const N: usize = 0; }
fn need<T: Tr>() {}
fn f() { need::<B<1>>(); }

Since this is strictly removing a panic and copying rustc, I haven't added a unit test with this.

AI disclosure: Triaged and minimised with help by an LLM, but commit message and final code by me.

rust-analyzer would panic when the trait solver called itself, which
can happen during const evaluation.

rustc has the same function, but doesn't panic, so just copy the rustc
implementation:

https://github.com/rust-lang/rust/blob/5392d2f545c6836dc79f209bcc14ac7179dbc4f2/compiler/rustc_middle/src/ty/context/impl_interner.rs#L155

This caused SCIP crashes on the dudykr/stc, renegade-fi/renegade, and
tikv/tikv GitHub repositories, so would presumably cause LSP crashes
too.

The linked trait-system-refactor-initiative issue has a repro, but for
reference I minimised a repro independently:

    trait Tr { const N: usize; }
    struct A<const N: usize>;
    impl<const N: usize> Tr for A<N> { const N: usize = N; }
    const fn k<T: Tr>() -> usize { T::N }
    struct B<const N: usize>;
    impl<const N: usize> Tr for B<N> where A<{ k::<A<3>>() }>: Tr { const N: usize = 0; }
    fn need<T: Tr>() {}
    fn f() { need::<B<1>>(); }

Since this is strictly removing a panic and copying rustc, I haven't
added a unit test with this.

AI disclosure: Triaged and minimised with help by an LLM, but commit
message and final code by me.
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 15, 2026

@ChayimFriedman2 ChayimFriedman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ChayimFriedman2
ChayimFriedman2 added this pull request to the merge queue Sep 15, 2026
Merged via the queue into rust-lang:master with commit 30cbc6f Sep 15, 2026
20 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 15, 2026
@Wilfred
Wilfred deleted the panic_on_solver_reentry branch September 15, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants