Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is referencing/borrowing needed in this case?

Tags:

rust

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:

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

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

like image 420
Martin Avatar asked Oct 18 '25 14:10

Martin


1 Answers

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 (left). 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
*/
like image 110
prog-fh Avatar answered Oct 21 '25 05:10

prog-fh