Deref &i32, novice question

hello everyone.
Learner question.
I thought I understood the automatic deref but obviously I have not! LOL.

Below is a code sample all using &i32.
The code below works identically and correctly whether I explicitly deferefence &i32 *n or leave as n.

What is the reason Rust does not insist I deference &i32 ?
Sorry about poor indentation, the code is tiny, should be easy to understand, I hope.

// block 1 uses *n deref
    let mut myvec = vec![0, 1, 2, 3, 4, 5];
    myvec.retain(|n| {
        println!("processing number: {}", *n);
        *n % 2 == 0 // *n is i32, ok
    });

// block 2 uses n (no deref, &i32)
    let mut myvec = vec![0, 1, 2, 3, 4, 5];
    myvec.retain(|n| {
        println!("processing number: {}", n);
        n % 2 == 0 // &i32 is OK too
    });

// block 3
    let n: &i32 = &20;
    if *n % 2 == 0 { // deref OK in the if statement
        println!("n is: {}", *n); // *n is ok, so is plain n also.
    }
// block 4
    if n % 2 == 0 { // &i32 is OK in if statement too
        println!("n is: {}", n);
    }

Thank you in advance.

Taking the remainder is OK because there is a Rem impl for &i32, and similarly println is okay because there's a transitive Display impl for all references &T when T is itself Display.

1 Like

thank you very much!

So in terms of Rust best practice should I explicitly deref *n in the above code?
What is more Rust idiomatic convention?

In such a simple case, it probably doesn't matter.

If I were doing something more complicated, I'd get rid of the reference upfront by pattern-matching on it in the argument:

vec.retain(|&n| {
    ...
});

because having a reference to a primitive can sometimes cause unintended effects, but having to dereference at 10 different places becomes ugly.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.