I'm doing a bit of type-level programming, and I've encountered a pattern that consistently seems to make rustc upset. I don't have a good mental model for why this is the case, and I'm hoping someone can shed some light. Playground link.

Let's say we define a type-level non-empty list, and a predicate Contains<E> that's satisfied if the type E appears in the list:

structOne<H>{}structCons<H,T>{}#[marker]traitContains<Needle>{}/// The needle is the only element of the list.impl<H>Contains<H>forOne<H>{}/// The needle is the first element of the list.impl<H,T>Contains<H>forCons<H,T>{}/// The needle is in the tail of the list.impl<E,H,T>Contains<E>forCons<H,T>whereT: Contains<E>{}

This works totally fine, as expected.

BUT, if we wrap each of the above types in another type, the compiler overflows evaluating the requirement Wrap<One<_>>: Contains<Wrap<_>>:

structWrap<T>(T);/// The needle is the only element of the list.impl<H>Contains<Wrap<H>>forWrap<One<H>>{}/// The needle is the first element of the list.impl<H,T>Contains<Wrap<H>>forWrap<Cons<H,T>>{}/// The needle is in the tail of the list.impl<E,H,T>Contains<Wrap<E>>forWrap<Cons<H,T>>whereWrap<T>: Contains<Wrap<E>>{}

Why does this happen? Is there a name for what's going on here? What causes the type checker to start recursively enumerating types?