# new solver hangs
## rigid alias as potentially non-rigid
https://github.com/rust-lang/trait-system-refactor-initiative/issues/109
two ideas:
#### eagerly reject definitely rigid aliases in normalizes-to
https://github.com/rust-lang/rust/pull/125334
does not work for rayon as rayon has a blanket impl whose nested goals fail instead
```rust
pub trait ParallelIterator {
type Item;
}
trait Trait {}
macro_rules! multizip_impl {
($($T:ident),+) => {
impl<$( $T, )+> Trait for ($( $T, )+)
where
$(
$T: ParallelIterator,
$T::Item: ParallelIterator<Item = u32>,
)+
{}
}
}
multizip_impl! { A, B, C, D, E, F, G, H, I, J, K, L }
fn main() {}
```
how this proceeds...
* proving `A: ParallelIterator`...
* we try `A::Item: ParallelIterator` and normalize `A::Item -> A`
* to do that normalization we look to show that `A: ParallelIterator`
* direct cycle
* we try `B::Item: ParallelIterator` and normalize `B::Item -> A`
* to do that normalization we look to show that `B: ParallelIterator`
* in the environment we find `B: ParallelIterator` but also `A::Item: ParallelIterator`, `C`, .. `L`
* same for `C`
...so we do `O(n!)` work.
Note that in original version there was no `Item = u32`.
in old solver:
* we do param-env normalization
* at each step, we assume that the existing where-clauses are rigid
where is it fruitful
```rust
// very easy
fn foo<A, B>()
where
A: Iterator<Item = B>,
A::Item: Iterator,
{}
// ---
// indirect, requires combining blanket impl with environment
fn foo<A, B>()
where
A: Iterator<Item = B>,
<A as IntoIterator>::Item: Iterator,
{}
impl<I: Iterator> IntoIterator for I {
type Item = <I as Iterator>::Item;
}
// ---
trait IteratorWithUnusedArg<T: ?Sized> {
type Item: ?Sized;
}
trait IntoIterator {
type Item: ?Sized;
}
fn foo<A, B>()
where
A: IteratorWithUnusedArg<<A as IntoIterator>::Item, Item = B>,
<A as IntoIterator>::Item: IteratorWithUnusedArg<u32>,
{}
impl<I: ?Sized + IteratorWithUnusedArg<<I as IntoIterator>::Item>> IntoIterator for I {
type Item = <I as IteratorWithUnusedArg<<I as IntoIterator>::Item>>::Item;
}
```
Hypothesis:
* The only way that normalizing `T = <P0 as Iterator<P1..Pn>>::Foo` can yield `Q` (where `Q` not free in `T`) is if there is some other thing in the environment that normalizes to a type `U` including `Q` ?
* this is what is impl'd in #124852
* but it cannot rule out `P0::Item = P0::OtherItem`, as in the impl in https://github.com/rust-lang/rust/issues/125269 (even if the cause of that hang is different)
* would be helped by the "is_rigid_alias" test described at first
* concern: currently have `for<'a> fn(&'a <?x as Subtrait<'a>>::Assoc)` will be `for<'a> where { ?x: Subtrait<'a> } fn(&'a <?x as Subtrait<'a>>::Assoc)`, with where-clauses on binders we end up putting `?x: Subtrait<'a>` into the environment inside of this function pointer, elaborating that could put `?x: Supertrait<Assoc = ?x>` into the env?
* Prolly not an issue in practice, have bigger issues with that anyways :3
#### eagerly fail "rigid-ty alias-relate alias" if the rigid type contains a placeholder not nameable by the alias
https://github.com/rust-lang/rust/pull/124852
Both fix some, but not all issues of this kind
## ambig alias != infer var weakens cycle detection
https://github.com/rust-lang/rust/issues/125269
- can be fixed by eagerly normalizing before evaluating nested goals: https://github.com/rust-lang/rust/pull/125343
## separate: highly involved cycles requiring >1 fixpoint iterations
- most notably fuchsia
Currently working on a search graph PR. Found another issue :<
*edit: 2 minutes ago I ended up questioning whether this is sound at all :3*
- `?t: Trait` with 2 candidates
- `impl<T> Trait for Vec<T> where T: Trait`
- first iteration, inductive cycle -> error
- `impl Trait for u32 {}`
- ok: `?t = u32`
- result of first iteration: `OK: ?t = u32`
- `impl<T> Trait for Vec<T> where T: Trait`
- first iteration, inductive cycle -> ok `?t: u32`
- result `?t = Vec<u32>`
- `impl Trait for u32 {}`
- ok: `?t = u32`
- result of second iteration `Ambig`
constraints from fixpoints aren't monotonically increasing :skull: