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

Bound on generic trait make compiler "forget" about another implementations of this trait #81448

Closed
Cerber-Ursi opened this issue Jan 27, 2021 · 4 comments
Labels
C-bug Category: This is a bug.

Comments

@Cerber-Ursi
Copy link
Contributor

This bug was initially reported on URLO and minimized to the following code:

use std::ops::Mul;

fn test<V>() where f32: Mul<V, Output = V> {
    let _: f32 = 1f32 * 1f32;
}

(Playground)

This code generates the following compile error, on any version of Rust I've checked down to 1.0.0 (with different format, obviously, but the same content):

error[E0308]: mismatched types
 --> src/lib.rs:4:25
  |
3 | fn test<V>() where f32: Mul<V, Output = V> {
  |         - this type parameter
4 |     let _: f32 = 1f32 * 1f32;
  |                         ^^^^ expected type parameter `V`, found `f32`
  |
  = note: expected type parameter `V`
                       found type `f32`

error[E0308]: mismatched types
 --> src/lib.rs:4:18
  |
3 | fn test<V>() where f32: Mul<V, Output = V> {
  |         - this type parameter
4 |     let _: f32 = 1f32 * 1f32;
  |            ---   ^^^^^^^^^^^ expected `f32`, found type parameter `V`
  |            |
  |            expected due to this
  |
  = note:        expected type `f32`
          found type parameter `V`

However, after adding another bound, it compiles successfully on all current versions (beta, stable and nightly):

use std::ops::Mul;

// the only difference is `+ Mul`
fn test<V>() where f32: Mul<V, Output = V> + Mul {
    let _: f32 = 1f32 * 1f32;
}
@Cerber-Ursi Cerber-Ursi added the C-bug Category: This is a bug. label Jan 27, 2021
@jonas-schievink
Copy link
Contributor

I believe this is working as intended. Predicates from where-clauses are preferred over impls from the environment.

@Cerber-Ursi
Copy link
Contributor Author

Not sure if I follow. Why should the predicate make the implementation known to the compiler (since they are obviously available without the where clause) unavailable?

@mpizenberg
Copy link

Hi, original urlo poster here. To me it makes little sense that the compiler would completely forget other implementations. And the only way that it could "compete" with the f32 implementation is if V becomes f32, but then we are fine too and 1f32 * 1f32 should be valid. In my use case, I need to express that V is some kind of vector type than can be multiplied by a scalar (here f32) so that I can do things like (1.0 + 2.0) * v but also (1.0 * 2.0) * v and the second one is the one that triggers the compiler error. Using Mul::<f32>::mul(1.0, 2.0) * v makes the compiler happy though so the trait implementation is definitely available, and both are compatible, it's just forgotten by the compiler.

@Cerber-Ursi
Copy link
Contributor Author

Cerber-Ursi commented Apr 13, 2021

As was found now by quinedot on URLO, this is in fact a duplicate of #24066, so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants