Repository: rust
Issue: Operator impl causes compilation error for an expression involving the operator with a different pair of types
Labels: A-trait-system,T-compiler,C-bug,T-types,fixed-by-next-solver

The existence of an implementation for `Add<Container<A>> for X where X: Add<A>` causes a compiler error under certain circumstances for expressions of the form `X + X`. Here's an example:

```rust
use std::ops::Add;

pub struct Container<T>(Vec<T>);

impl<A, B> Add<Container<A>> for f32
where
    f32: Add<A, Output = B>,
{
    type Output = B;
    fn add(self, _rhs: Container<A>) -> B {
        unimplemented!()
    }
}

fn doesnt_compile<'a, V>(a: V) -> f32
where
    V: Into<Container<&'a f32>>,
{
    let a: Container<&'a f32> = a.into();
    0f32 + 1f32
}
```

([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=29c9a7a05f3becc08931d5761a4a4fb5))

I expected this to compile without errors. Instead, I receive the following error message (abbreviated below):

```
error[E0275]: overflow evaluating the requirement `f32: Add<Container<_>>`
  --> src/main.rs:20:10
   |
20 |     0f32 + 1f32
   |          ^
   |
   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
   = note: required because of the requirements on the impl of `Add<Container<Container<_>>>` for `f32`
   = note: required because of the requirements on the impl of `Add<Container<Container<Container<_>>>>` for `f32`
   = note: required because of the requirements on the impl of `Add<Container<Container<Container<Container<_>>>>>` for `f32`
   = note: required because of the requirements on the impl of `Add<Container<Container<Container<Container<Container<_>>>>>>` for `f32`
   = note: required because of the requirements on the impl of `Add<Container<Container<Container<Container<Container<Container<_>>>>>>>` for `f32`
...
```

Observe that even though the addition is between two `f32` literals, the error message indicates that the compiler is trying to apply the impl involving `Container`.

Note that it still fails to compile if I replace `f32` with a custom struct.

To help diagnose the issue, it's helpful to note that replacing the `doesnt_compile` function with any of the following similar functions causes the example to compile without errors:

```rust
fn compiles1<'a, V>(a: V) -> f32
where
    V: Into<Container<&'a f32>>,
{
    let a: Container<&'a f32> = a.into();
    1f32
}

fn compiles2<'a>(a: Container<&'a f32>) -> f32 {
    0f32 + 1f32
}

fn compiles3<V>(a: V) -> f32
where
    V: Into<Container<f32>>,
{
    let a: Container<f32> = a.into();
    0f32 + 1f32
}
```

We first observed the issue in a more complicated case in the `ndarray` crate. ([See the discussion here.](https://github.com/rust-ndarray/ndarray/pull/782#pullrequestreview-559666435)) This bug report is a simplified example. Edit: Interestingly, in the more complicated case, we observed differing error messages between different platforms.

### Meta

Stable (1.48.0), Beta (1.50.0-beta.1, 2020-12-29), and Nightly (1.51.0-nightly, 2020-12-29) all produce a compilation error (tested with the Rust Playground).

On my machine, `rustc --version --verbose`:
```
rustc 1.48.0 (7eac88abb 2020-11-16)
binary: rustc
commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
commit-date: 2020-11-16
host: x86_64-unknown-linux-gnu
release: 1.48.0
LLVM version: 11.0
```