Infinite recursion in type resolution for unused type
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
Example:
use std::collections::HashMap;
use std::marker::PhantomData;
trait Resource {}
struct Res<'w, T: ?Sized + Resource>(&'w T);
impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
trait Matcher<T> {}
impl<'a, A, B, U: Matcher<&'a A>, V: Matcher<&'a B>> Matcher<(&'a A, &'a B)> for (U, V) {}
struct EqMatcher<T>(PhantomData<T>);
impl<T> Matcher<T> for EqMatcher<T> {}
struct ContainerMatcher<T>(Box<dyn Matcher<T>>);
impl<T, ContainerT> Matcher<ContainerT> for ContainerMatcher<T> where
ContainerT: IntoIterator<Item = T>
{
}
#[test]
fn it_works() {
// todo just to get the types to work.
let matcher: Box<(EqMatcher<&u32>, ContainerMatcher<(&u32, &u32)>)> = todo!();
// This is converting the Box into a Box<dyn Matcher>
let bad_matcher = ContainerMatcher(matcher);
let blah = HashMap::<u32, HashMap<u32, u32>>::default();
fn check<T>(val: T, matcher: impl Matcher<T>) {}
check(&blah, bad_matcher);
}
As a short summary: I am implementing a trait for one struct to operate on anything that impls IntoIterator. In addition this trait "distributes" to elements in a pair. I then try and merge these two properties to construct bad_matcher. For context, this happens as a result of merging the googletest and bevy_ecs crates.
I expected to see this happen: The test to compile.
Instead, this happened: Failed to compile due to infinite recursion of the Res type (which is completely unused).
error[E0275]: overflow evaluating the requirement `&_: IntoIterator`
--> src\lib.rs:38:40
|
38 | let bad_matcher = ContainerMatcher(matcher);
| ^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`bevy_googletest`)
note: required for `&Res<'_, _>` to implement `IntoIterator`
--> src\lib.rs:8:27
|
8 | impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
| ^^^^^^^^^^^^ ^^^^^^^^^^^^^^
9 | where
10 | &'a T: IntoIterator,
| ------------ unsatisfied trait bound introduced here
= note: 123 redundant requirements hidden
= note: required for `&Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, ...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implem
ent `IntoIterator`
note: required for `ContainerMatcher<(&u32, &u32)>` to implement `Matcher<&Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<
'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res
<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Re
s<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, _>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> src\lib.rs:30:21
|
30 | impl<T, ContainerT> Matcher<ContainerT> for ContainerMatcher<T> where
| ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
31 | ContainerT: IntoIterator<Item = T>
| -------- unsatisfied trait bound introduced here
= note: 1 redundant requirement hidden
= note: required for `(EqMatcher, ContainerMatcher<(&u32, &u32)>)` to implement `Matcher<(&u32, &Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res
<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Re
s<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, R
es<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, _>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>)>`
= note: required for the cast from `Box<(EqMatcher, ContainerMatcher<(&u32, &u32)>)>` to `Box<dyn Matcher<(&u32, &Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Res<'_, Re
s<'_, Res<'_, Res<'_, ...>>>>>>>>>>>>>>>>>>>>>>>>>>>>)>>`
= note: the full name for the type has been written to 'E:\Content\bevy_googletest\target\debug\deps\bevy_googletest-3fef145a913b892a.long-type-9581655154092012888.txt'
= note: consider using `--verbose` to print the full type name to the console
= note: the full name for the type has been written to 'E:\Content\bevy_googletest\target\debug\deps\bevy_googletest-3fef145a913b892a.long-type-1543903567385044461.txt'
= note: consider using `--verbose` to print the full type name to the console
Meta
rustc --version --verbose:
rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: x86_64-pc-windows-msvc
release: 1.83.0
LLVM version: 19.1.1
This seems to be fixed with -Znext-solver.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the minimal example in src/lib.rs with rustc 1.83.0, then compare the default solver with -Znext-solver. Inspect the emitted long-type files and the overflow chain to determine why the unused Res type enters trait evaluation. Done should include a regression test showing the example compiles without recursive type-resolution overflow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100