Why isn't it possible to compare a borrowed in

2020-02-28 04:39发布

问题:

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.

回答1:

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.)