Repository navigation
Closed as not planned
Closed as not planned
Copy link
Labels
C-bugCategory: This is a bug.Category: This is a bug.F-const_trait_impl`#![feature(const_trait_impl)]``#![feature(const_trait_impl)]`F-generic_const_exprs`#![feature(generic_const_exprs)]``#![feature(generic_const_exprs)]`I-cycleIssue: A query cycle occurred while none was expectedIssue: A query cycle occurred while none was expectedT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Description
I tried this code:
#![feature(const_convert, const_trait_impl, generic_const_exprs)]
#![expect(incomplete_features, reason = "generic_const_exprs")]
pub mod b {
pub struct WrapperB([u8; WrapperB::SIZE]);
impl From<WrapperB> for [u8; WrapperB::SIZE] {
fn from(value: WrapperB) -> Self {
<[u8; WrapperB::SIZE]>::from(value.0)
}
}
impl WrapperB {
pub const SIZE: usize = 32;
}
}
pub mod a {
pub struct WrapperA([u8; WrapperA::SIZE]);
impl From<[u8; WrapperA::SIZE]> for WrapperA {
fn from(value: [u8; WrapperA::SIZE]) -> Self {
WrapperA(value)
}
}
impl WrapperA {
pub const SIZE: usize = usize::from(1u8);
}
}I expected to see this happen: Compiles without errors
Instead, this happened:
Details
error[E0391]: cycle detected when coherence checking all impls of trait `core::convert::From`
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:588:1
|
588 | pub const trait From<T>: Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires building specialization graph of trait `core::convert::From`...
--> src/lib.rs:20:20
|
20 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> src/lib.rs:20:20
|
20 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `a::<impl at src/lib.rs:20:5: 20:49>::{constant#0}`...
--> src/lib.rs:20:20
|
20 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires checking if `a::<impl at src/lib.rs:20:5: 20:49>::{constant#0}` is a trivial const...
--> src/lib.rs:20:20
|
20 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires building MIR for `a::<impl at src/lib.rs:20:5: 20:49>::{constant#0}`...
--> src/lib.rs:20:20
|
20 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires checking if `a::<impl at src/lib.rs:26:5: 26:18>::SIZE` is a trivial const...
--> src/lib.rs:27:9
|
27 | pub const SIZE: usize = usize::from(1);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for `a::<impl at src/lib.rs:26:5: 26:18>::SIZE`...
--> src/lib.rs:27:9
|
27 | pub const SIZE: usize = usize::from(1);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires match-checking `a::<impl at src/lib.rs:26:5: 26:18>::SIZE`...
--> src/lib.rs:27:9
|
27 | pub const SIZE: usize = usize::from(1);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `a::<impl at src/lib.rs:26:5: 26:18>::SIZE`...
--> src/lib.rs:27:9
|
27 | pub const SIZE: usize = usize::from(1);
| ^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires coherence checking all impls of trait `core::convert::From`, completing the cycle
note: cycle used when checking that `b::<impl at src/lib.rs:7:5: 7:49>` is well-formed
--> src/lib.rs:7:5
|
7 | impl From<WrapperB> for [u8; WrapperB::SIZE] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
Even more confusingly, rearranging modules a and b results in a different error, but it also mentions cycles:
Details
error[E0391]: cycle detected when checking if `a::<impl at src/lib.rs:13:5: 13:18>::SIZE` is a trivial const
--> src/lib.rs:14:9
|
14 | pub const SIZE: usize = usize::from(1u8);
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires building MIR for `a::<impl at src/lib.rs:13:5: 13:18>::SIZE`...
--> src/lib.rs:14:9
|
14 | pub const SIZE: usize = usize::from(1u8);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires match-checking `a::<impl at src/lib.rs:13:5: 13:18>::SIZE`...
--> src/lib.rs:14:9
|
14 | pub const SIZE: usize = usize::from(1u8);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `a::<impl at src/lib.rs:13:5: 13:18>::SIZE`...
--> src/lib.rs:14:9
|
14 | pub const SIZE: usize = usize::from(1u8);
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires coherence checking all impls of trait `core::convert::From`...
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:588:1
|
588 | pub const trait From<T>: Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building specialization graph of trait `core::convert::From`...
--> src/lib.rs:7:20
|
7 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> src/lib.rs:7:20
|
7 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `a::<impl at src/lib.rs:7:5: 7:49>::{constant#0}`...
--> src/lib.rs:7:20
|
7 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires checking if `a::<impl at src/lib.rs:7:5: 7:49>::{constant#0}` is a trivial const...
--> src/lib.rs:7:20
|
7 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
note: ...which requires building MIR for `a::<impl at src/lib.rs:7:5: 7:49>::{constant#0}`...
--> src/lib.rs:7:20
|
7 | impl From<[u8; WrapperA::SIZE]> for WrapperA {
| ^^^^^^^^^^^^^^
= note: ...which again requires checking if `a::<impl at src/lib.rs:13:5: 13:18>::SIZE` is a trivial const, completing the cycle
note: cycle used when building MIR for `a::WrapperA::0::{constant#0}`
--> src/lib.rs:5:30
|
5 | pub struct WrapperA([u8; WrapperA::SIZE]);
| ^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
Meta
rustc --version --verbose:
rustc 1.97.0-nightly (365c0e1d7 2026-05-06)
binary: rustc
commit-hash: 365c0e1d7a614ca94cb48431dcd2bc6d3b645db1
commit-date: 2026-05-06
host: x86_64-unknown-linux-gnu
release: 1.97.0-nightly
LLVM version: 22.1.4
The first version that fails is nightly-2026-05-04:
rustc 1.97.0-nightly (ad3a598ca 2026-05-03)
binary: rustc
commit-hash: ad3a598ca4bc7c68bcbbce3e0d3be9a7618df190
commit-date: 2026-05-03
host: x86_64-unknown-linux-gnu
release: 1.97.0-nightly
LLVM version: 22.1.4
The last version that works correctly is nightly-2026-05-03:
rustc 1.97.0-nightly (20de910db 2026-05-02)
binary: rustc
commit-hash: 20de910db49d3476ccf49ea79a4b22e2b5dface0
commit-date: 2026-05-02
host: x86_64-unknown-linux-gnu
release: 1.97.0-nightly
LLVM version: 22.1.4
Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.F-const_trait_impl`#![feature(const_trait_impl)]``#![feature(const_trait_impl)]`F-generic_const_exprs`#![feature(generic_const_exprs)]``#![feature(generic_const_exprs)]`I-cycleIssue: A query cycle occurred while none was expectedIssue: A query cycle occurred while none was expectedT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Activity
nazar-pc commentedon May 14, 2026
I'd really appreciate if this regression could be tracked down. I understand this is an unstable feature, but having something like this seems to make generic const expressions essentially unusable, while previously they just required a large number of hacks and workarounds.
theemathas commentedon May 14, 2026
@nazar-pc You can use cargo-bisect-rustc to figure out which PR caused this regression.
Unfortunately though,
generic_const_exprsis a rather broken feature, and there's a good chance that it might be removed from the compiler completely, and replaced withmin_generic_const_args.nazar-pc commentedon May 15, 2026
Thanks, I didn't know about cargo-bisect-rustc before.
ad3a598 is the commit with regression, which points to #156113.
theemathas commentedon May 15, 2026
cc @zedddie and @BoxyUwU (author and reviewer of #153536, which seems to have regressed this)
BoxyUwU commentedon May 15, 2026
would be useful to figure out what's going on here as there might be non-GCE impact
zedddie commentedon May 15, 2026
this goes from a3e96d8, which is in #155767
BoxyUwU commentedon May 15, 2026
ah thx zedddie, this seems not worth fixing then unfortunately. @nazar-pc you might want to try porting your code over to
feature(generic_const_args)nazar-pc commentedon May 15, 2026
Hm, so
generic_const_exprsis now essentially perma-broken if even something as basic aspub const SIZE: usize = usize::from(1u8);is no longer supported?BoxyUwU commentedon May 15, 2026
hmm dont understand what's going on here and also won't really have time to look into it for a bit
theemathas commentedon May 16, 2026
Should this reissue be reopened, then? I'm not sure I understand what's going on.
BoxyUwU commentedon May 16, 2026
I think what's going on is that coherence uses the new solver and the new solver also just doesn't support GCE and currently things are being changed about how normalization works in the new solver (which affects coherence). In theory GCE should only be more broken when it comes to const arguments in impl headers, but I do agree that it's significantly more broken now than it was before which is quite unfortunate ^^'
I think
generic_const_argsis "ready" enough for people to migrate off of GCE to it at this point and generally is what people should do as GCE won't stick around for much longer, regardless of the fact that its support has been gradually degrading over the last couple years. Given this, I don't think GCE is important enough to revert or block any of the work happening around normalization in the new solver, but yeah sorry for GCE kinda falling apart.nazar-pc commentedon May 16, 2026
Well,
generic_const_argsseems too limiting today. The first method I needed to refactor was:But it is not supported:
I completely understand the desire and benefits of completing/stabilizing something more minimal, but such things are everywhere in my project.
BoxyUwU commentedon May 18, 2026
Would you be able to open a thread in #project-const-generics on the rust zulip titled sth like "help migrating from GCE to GCA"? I (and others) will be able to help you with migrating from GCE to GCA.
Other than that, the diagnositc you're getting sure is unfortunate 😅 does not set you up for success (i will file a bug for this). The way GCA works is that it allows arbitrary paths to const items including generics. so you can do
const FOO<T>: usize = size_of::<T>();and then[u8; FOO<T>]but you can't do[u8; size_of::<T>()].