-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
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:
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
}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:
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.) 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