Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is referencing/borrowing needed in this case?

I’m new to rust and just played around with some code:

fn array_leaders(arr: &[i32]) -> Vec<i32> {
    let mut res = Vec::new();
    for (i, left) in arr.iter().enumerate() {
        let right = arr.iter().skip(i+1).sum();
        if left > right { res.push(*left) };
    }
    res
}

which gives the following error:

error[E0277]: the trait bound `&i32: Sum<&i32>` is not satisfied
    --> src/lib.rs:5:42
     |
5    |         let right = arr.iter().skip(i+1).sum();
     |                                          ^^^ the trait `Sum<&i32>` is not implemented for `&i32`

Now, I’ve figured out that i could just add an & to the right variable in the if statement:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

        if left > &right { res.push(*left) };

which solves the problem. I would like to understand why though

>Solution :

It’s because left has type &i32 (generated via .iter()) but right as type i32 (generated by sum()).

We could compare *left against right (two i32).

Rust also enables the comparison through references: left against &right (two &i32).

The same level of indirection must be present on both sides of the comparison.

The short example below tries to illustrate this.

Moreover, as stated in a comment, Rust tries to deduce the types that are not strictly imposed (when some alternatives exist).
Here, the type of left is imposed by .iter() but the return type of sum() could be deduced.
Then Rust tries to find an implementation of sum() that matches &i32 because this result will be compared against i32. This cannot be found here, thus the error.

fn main() {
    let a = 5;
    for b in 3..=7 {
        let r_a = &a;
        let r_b = &b;
        let cmp1 = a < b;
        let cmp2 = r_a < r_b;
        let cmp3 = *r_a < *r_b;
        println!("{} < {} --> {} {} {}", a, b, cmp1, cmp2, cmp3);
    }
}
/*
5 < 3 --> false false false
5 < 4 --> false false false
5 < 5 --> false false false
5 < 6 --> true true true
5 < 7 --> true true true
*/
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading