Open
Description
The current stable trait solver may enter an infinite recursion when recursively-implemented traits with additional implementation parameters used without full type annotations (with type inference).
Compilation success depends on the compilation cache (see fn1
comments).
This issue is resolved in next-generation trait solver (RUSTFLAGS="-Znext-solver"
).
Code
pub trait Trait<T> {
type Ty;
// Error remains for `fn get() -> Result<T, Self::Ty>`.
// Error remains for `fn get(&self) -> (T, Self::Ty);`.
fn get() -> (T, Self::Ty);
}
// Error remains for `impl<C, T, A> Trait<&'static T>> for C`
// Error remains for `impl<C, T, A> Trait<Box<T>> for C`
// Error remains for `impl<C, T, A> Trait<Option<T>> for C`
// Error remains for `impl<C, T, E, A> Trait<Result<T, E>> for C`
impl<C, T, A> Trait<(T,)> for C
where
C: Trait<T, Ty = A>,
{
// Removing `A` impl argument and using `type Ty = C::Ty;` fixes the error.
type Ty = A;
fn get() -> ((T,), Self::Ty) {
todo!()
}
}
struct Type;
// Error remains when using other primitive types instead of `u8`.
impl Trait<u8> for Type {
type Ty = ();
fn get() -> (u8, Self::Ty) {
todo!()
}
}
// Uncommenting the function below fixes the compilation of `fn2`.
// Compilation is fixed only if `fn1` is located before `fn2`.
// Commenting it back doesn't break the compilation of `fn2` back.
// Using `cargo clean` with commented `fn1` will break the compilation back.
// fn fn1() {
// let res: ((u8,), ()) = Type::get();
// }
// This fails to compile.
fn fn2() {
let res: ((u8,), ()) = <Type as Trait<(_,)>>::get();
}
// This succeeds to compile.
fn fn3() {
// Fully-specified trait arguments fixes the issue.
let res: ((u8,), ()) = <Type as Trait<(u8,)>>::get();
}
Checked with: cargo check
Expected: success
Result:
error[E0275]: overflow evaluating the requirement `Type: Trait<(_,)>`
--> src/lib.rs:43:28
|
43 | let res: ((u8,), ()) = <Type as Trait<(_,)>>::get();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`test_lib2`)
note: required for `Type` to implement `Trait<((_,),)>`
--> src/lib.rs:12:15
|
12 | impl<C, T, A> Trait<(T,)> for C
| ^^^^^^^^^^^ ^
13 | where
14 | C: Trait<T, Ty = A>,
| ------ unsatisfied trait bound introduced here
= note: 127 redundant requirements hidden
= note: required for `Type` to implement `Trait<(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((_,),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),),)>`
Meta
Affected Rust versions:
- 1.31.0 - reproducible.
- Stable (
rustc 1.88.0 (6b00bc388 2025-06-23)
) - reproducible. - Beta (
rustc 1.89.0-beta.3 (b5e10d8c0 2025-07-02)
)- reproducible. - Nightly (
rustc 1.90.0-nightly (da58c0513 2025-07-03)
) - reproducible.
$ rustc --version --verbose
rustc 1.88.0 (6b00bc388 2025-06-23)
binary: rustc
commit-hash: 6b00bc3880198600130e1cf62b8f8a93494488cc
commit-date: 2025-06-23
host: x86_64-unknown-linux-gnu
release: 1.88.0
LLVM version: 20.1.5
The issue doesn't occur when using RUSTFLAGS="-Znext-solver" cargo +nightly check