Strange auto dereference error

these doesn't compile:

use std::ops::Deref;

struct M(i32);
impl Deref for M {
    type Target = i32;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
//fn f(_x: &i32, _y: &i32) {}
fn main() {
    let a = 100;
    let b = M(100);

    //f(&a, &b);

    let c = a.eq(&b);
    println!("{}", c);
}

error[E0277]: can't compare `{integer}` with `M`
  --> src/main.rs:18:15
   |
18 |     let c = a.eq(&b);
   |               ^^ no implementation for `{integer} == M`
   |
   = help: the trait `PartialEq<M>` is not implemented for `{integer}`

these compile:

use std::ops::Deref;

struct M(i32);
impl Deref for M {
    type Target = i32;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
fn f(_x: &i32, _y: &i32) {}
fn main() {
    let a = 100;
    let b = M(100);

    f(&a, &b);

    let c = a.eq(&b);
    println!("{}", c); //true
}

How so?

I think acrossing to “ If T implements Deref<Target = U> , and x is a value of type T , then: Values of type &T are coerced to values of type &U ” from Deref in std::ops - Rust , all should compile.

I think it's just the usual "generics and coercions mix poorly" problem.

PartialEq::eq comes from a trait and has a generic parameter. So it looks for PartialEq<M>, which could exists. And thus because it hit a generic, it doesn't then try to apply coercions.

Basically, coercions are annoying. They don't fit well with type inference.

2 Likes

To add a little detail, the signature of PartialEq<Rhs>::eq is

fn eq(&self, other: &Rhs) -> bool;

And when coercing against the type of the method parameter, you're coercing a &M against a &Generic which can "succeed" by letting Generic=M (only for the code to fail when the trait is found to not be implemented).

With the function f, the argument parameter is a &i32, which doesn't "succeed" against a &M, so coercion continues.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.