Skip to content

Infinite recursion in type resolution for unused type #134719

Open
@andriyDev

Description

@andriyDev

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable ExampleI-hangIssue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc.T-typesRelevant to the types team, which will review and decide on the PR/issue.fixed-by-next-solverFixed by the next-generation trait solver, `-Znext-solver`.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions