Compare a reference and a value

Currently, 2 == 2 works, and &2 == &2 works with the same semantics, but compiler rejects 2 == &2:

error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src/main.rs:4:15
  |
4 |     let y = x == &x;
  |               ^^ no implementation for `{integer} == &{integer}`
  |
  = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`

What was the reason behind this decision?

2 Likes

This has been an open issue since 2017, I guess it is harder to fix than it sounds.

It looks like someone got it basically working here: GitHub - peckpeck/rust at autoref_op

It looks like it'll need cleanup and polish, but it's not insurmountable if someone wanted to take it (I think, I've never touched the compiler)

Does it works for nested comparisons, like Some(2) == Some(&2)

Why not x == *&x or &x == &x? IMHO comparing usize and i32 looks at least weird :face_with_monocle:

Note that for any user defined type T, it is possible to implement PartialEq for any RHS:

impl PartialEq<MyLittleType> for T {
   ... 
} 

So a general impl PartialEq<&T> for T is not possible, but what about special implementation for primitives, like impl PartialEq<&i32> for i32? Standard library already has such implementations, like impl PartialEq<&str> for String or impl PartialEq<&[T]> for [T; N].

I find auto-(de)ref rules confusing already -- most people don't even know how they work exactly, which is a bad state to be in. I think it's better not to add even more auto-(de)ref rules into the language.

5 Likes

We've tried to do this kind of thing a few times, and the problem we regularly run into is that doing so breaks programs relying on type inference. While we don't consider inference failure an absolute showstopper to introducing something, these changes tend to cause widespread issues in enough Rust code to make them nonstarters.

2 Likes

Hmm, what kind of code can break? I tried this code:

fn main() {
    let x: i32 = 5;
    let cl = |y: _| y == x;
}

And it seems compiler is already unable to infer type of y.

If it causes a breaking change, is it possible to ignore some trait implementations in some editions for type inference?

Where can I read about last few tries? I want to investigate this.

1 Like

If this is the biggest or even only blocker, could this then be resolved in the next edition?

How would you handle changing it in an edition without breaking older macros in crates using a newer edition?

And compare T and Option<T>?