5

This is what the std says:

pub trait PartialEq<Rhs: ?Sized = Self> {
    /// This method tests for `self` and `other` values to be equal, and is used
    /// by `==`.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn eq(&self, other: &Rhs) -> bool;

    /// This method tests for `!=`.
    #[inline]
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn ne(&self, other: &Rhs) -> bool {
        !self.eq(other)
    }
}

And the link: https://doc.rust-lang.org/src/core/cmp.rs.html#207

This is my code:

fn main() {
    let a = 1;
    let b = &a;
    println!("{}", a==b);
}

and the compiler told me:

error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src\main.rs:4:21
  |
4 |     println!("{}", a==b);
  |                     ^^ no implementation for `{integer} == &{integer}`    
  |
  = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`

But when I used eq(), it compiled:

fn main() {
    let a = 1;
    let b = &a;
    println!("{}", a.eq(b));
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
sssqqq
  • 53
  • 4

2 Answers2

10

It's actually quite simple, but it requires a bit of knowledge. The expression a == b is syntactic sugar for PartialEq::eq(&a, &b) (otherwise, we'd be moving a and b by trying to test if they're equal if we're dealing with non-Copy types).

In our case, the function PartialEq::eq needs to take two arguments, both of which are of type &i32. We see that a : i32 and b : &i32. Thus, &b will have type &&i32, not &i32.

It makes sense that we'd get a type error by trying to compare two things with different types. a has type i32 and b has type &i32, so it makes sense that no matter how the compiler secretly implements a == b, we might get a type error for trying to do it.

On the other hand, in the case where a : i32, the expression a.eq(b) is syntactic sugar for PartialEq::eq(&a, b). There's a subtle difference here - there's no &b. In this case, both &a and b have type &i32, so this is totally fine.

Mark Saving
  • 1,752
  • 7
  • 11
5

The difference between a.eq(b) and a == b in that dot operator does autoref/autoderef on receiver type for call-by-reference methods.

So when you write a.eq(b) compiler looks at PartialEq::eq(&self, other: &Rhs) signature, sees &self reference and adds it to a.

When you write a == b it desugars to PartialEq::eq(a, b) where a: i32 b: &i32 in your case, hence the error no implementation for `{integer} == &{integer}` .

But why it does not do the same in operators? See Tracking issue: Allow autoderef and autoref in operators (experiment) #44762

Related information: What are Rust's exact auto-dereferencing rules?

Dawer
  • 309
  • 1
  • 6
  • This should be the accepted answer. The auto-referencing done by the dot operator is the key reason why only `a.eq(b)` works. – QuestionDriven Aug 28 '23 at 16:35