48

I want to get the elements in an array where a condition is true. For example. I would like all indices where the array elements are 0:

fn main() {
    let lim = 10;
    let mut sieve = vec![0; lim + 1];
    sieve[1] = 1;
    println!(
        "{:?}",
        sieve
            .iter()
            .enumerate()
            .filter(|&(_, c)| c != 0)
            .map(|(i, _)| i)
            .collect::<Vec<usize>>()
    );
}

But this is a compile error:

error[E0277]: can't compare `&{integer}` with `{integer}`
  --> src/main.rs:10:33
   |
10 |             .filter(|&(_, c)| c != 0)
   |                                 ^^ no implementation for `&{integer} == {integer}`
   |
   = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&{integer}`

When I use c.clone() != 0 it works.

If I understand the error message correctly, Rust complains that it can't compare a borrow to an integer with an integer. I don't see why it shouldn't be possible.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Max Linke
  • 1,705
  • 2
  • 18
  • 24

1 Answers1

55

You interpret the error correctly, and the reason is that it simply isn't implemented. If the standard library writers wanted to make this work, they'd have to implement PartialEq for &i32 == i32, i32 == &i32, &mut i32 == i32, i32 == &mut i32, &i32 == &mut i32 and &mut i32 == &i32. And then they'd have to do that for all other primitive types (i8, i16, u8, u16, u32, i64, u64, f32, f64, and char).

That's a lot of PartialEq implementations.

Or instead they can just ask the users of the language to write *c != 0.

(If you're coming from C++, the key thing to understand is that syntactically, borrows are more like pointers than references. Only method call syntax has the auto-deref feature.)

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • 13
    Only two additional implementation per type would be needed – `&i32 == i32` and `i32 == &i32`. The comparison `&i32 == &32` already works by virtue of deref coercions, and mutable references coerce to immutable references, so no separate implementations are required. This doesn't really make a difference for the point you make, but I thought it's still worth commenting. – Sven Marnach Jan 09 '19 at 00:06
  • But there is auto-dereferencing rules. As I see, `b==32` – Tokubara Mar 20 '21 at 14:40
  • they could have used macros to do it :D another question, is it better to dereference (*a > b) or borrow? (a > &b) ? Or are both equivalent once compiled anyway? – David 天宇 Wong Aug 05 '21 at 19:41
  • I would dereference, but it's unlikely they're going to have different assembly after optimization. – Sebastian Redl Aug 05 '21 at 20:04
  • 2
    Is there an risk of actual undefined behaviour if these `PartialEq`s were implemented? For every other Rust design decision that I've been initially irritated by, I've quickly been able to see that it's actually preventing me from shooting myself in the foot (e.g. [comparing integers of different types](https://stackoverflow.com/questions/48225587/why-cant-i-compare-two-integers-of-different-types) _may_ be a sign of a bug) - but I'm not able to see an actual danger case, here. Is there one? – scubbo Apr 05 '23 at 03:47