Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Operator impl causes compilation error for an expression involving the operator with a different pair of types #80542

Open
jturner314 opened this issue Dec 31, 2020 · 1 comment
Labels
A-traits Area: Trait system C-bug Category: This is a bug. fixed-by-next-solver Fixed by the next-generation trait solver, `-Znext-solver`. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@jturner314
Copy link
Contributor

jturner314 commented Dec 31, 2020

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
}

(playground)

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
@jturner314 jturner314 added the C-bug Category: This is a bug. label Dec 31, 2020
@jturner314 jturner314 changed the title Operator impl causes compilation error for an expression of the operator with unrelated types Operator impl causes compilation error for an expression involving the operator with unrelated types Dec 31, 2020
@jturner314 jturner314 changed the title Operator impl causes compilation error for an expression involving the operator with unrelated types Operator impl causes compilation error for an expression involving the operator with a different pair of types Dec 31, 2020
@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@fmease fmease added A-traits Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. and removed needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. labels Jan 25, 2024
@fmease
Copy link
Member

fmease commented Jan 25, 2024

Successfully compiles in the next-gen solver (-Znext-solver).

@fmease fmease added the fixed-by-next-solver Fixed by the next-generation trait solver, `-Znext-solver`. label Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-traits Area: Trait system C-bug Category: This is a bug. fixed-by-next-solver Fixed by the next-generation trait solver, `-Znext-solver`. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants