Repository: rust
Issue: Compilation fails when explicit types are not provided, despite satisfied trait bounds
Labels: A-trait-system,T-compiler,C-bug,T-types

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

EDIT: See [further minified code](https://github.com/rust-lang/rust/issues/91701#issuecomment-989830714) in subsequent replies.

Consider the following code ([Playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=04a1c2b4aa094033801ad3f051f25a8a)): 

```rust
pub struct X;

pub trait Pair<A, B = ()> {}

pub trait One<A>: Pair<A> + Pair<A, A> {}
pub trait Two<A, B>: One<A> + One<B> + Pair<A, B> + Pair<B, A> {}
pub trait Three<A, B, C>: Two<A, B> + Two<A, C> + Two<B, C> {}

impl<A, B> Two<A, B> for X
where
    X: One<A> + One<B> + Pair<A, B> + Pair<B, A>
{}

impl<A, B, C> Three<A, B, C> for X
where
    X: Two<A, B> + Two<A, C> + Two<B, C>
{}

pub fn foo1<A, B, C>(_a: A, _b: B, _c: C)
where
    X: Three<A, B, C>
{}

// Calls foo1 but we have a different order of types in the trait bound.
// However, the traits are defined so that the order technically does not
// matter: if one order is satisfied, then it's satisfied for all
// possible orderings. This is evidenced by the fact that it works with
// a different order than the trait ordering if we *explicitly* specify
// the types. However, without explicitly specifying types, type inference
// fails.
pub fn foo2<Z, A, B, C>(a: A, b: B, c: C)
where
    // Note different order of parameters
    X: Three<A, C, B>,
{
    // Fails due to type inference
    foo1(a, b, c);
    
    // Works when types are explicitly named
    // foo1::<A, B, C>(a, b, c);
}
```

I expected to see this happen: Both manners of calling `foo1` should work.

Instead, this happened: Only the variant where the types are explicitly named compiles. Here's the error:

```
error[E0308]: mismatched types
  --> src/lib.rs:37:13
   |
31 | pub fn foo2<A, B, C>(a: A, b: B, c: C)
   |                -  - expected type parameter
   |                |
   |                found type parameter
...
37 |     foo1(a, b, c);
   |             ^ expected type parameter `C`, found type parameter `B`
   |
   = note: expected type parameter `C`
              found type parameter `B`
   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

error[E0308]: mismatched types
  --> src/lib.rs:37:16
   |
31 | pub fn foo2<A, B, C>(a: A, b: B, c: C)
   |                -  - found type parameter
   |                |
   |                expected type parameter
...
37 |     foo1(a, b, c);
   |                ^ expected type parameter `B`, found type parameter `C`
   |
   = note: expected type parameter `B`
              found type parameter `C`
   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 2 previous errors
```

### Meta

I've tried this on Stable 1.57 and the current nightly on the playground (1.59.0-nightly (2021-12-07 0b6f079e4987ded15c13)).

For context, this minified code is representative of some fairly involved generic code that works with the `Allocator` bounds used by `nalgebra`. For example, the [TriDimAllocator trait from fenris](https://docs.rs/fenris/0.0.14/fenris/allocators/trait.TriDimAllocator.html) is essentially analogous to `Three` in the above example.