4
\$\begingroup\$

I wrote some code that set the last few elements of an array to zero. I call these last elements the "excess":

const MAX_DIGITS: usize = 20;
pub fn zero_excess_digits(digits: &mut [u8; MAX_DIGITS], n_digits: usize) {
    for i in n_digits..MAX_DIGITS {
        digits[i] = 0;
    }
}

However, Clippy considers this a needless_range_loop and suggests I write the code like this:

const MAX_DIGITS: usize = 20;
pub fn zero_excess_digits_iter_for(digits: &mut [u8; MAX_DIGITS], n_digits: usize) {
    for d in digits.iter_mut().take(MAX_DIGITS).skip(n_digits) {
        *d = 0;
    }
}

Usually when I've used Clippy, it's given me solid advice. But in this case, I just don't see it. I've tried both versions in Godbolt/Compiler Explorer: https://godbolt.org/z/7G8McseKs

  1. it optimizes my original version to a call to memset (12 lines of asm);
  2. for the .iter_mut() version, it generates code for the loop (30 lines of asm! Unacceptable!)
  3. I tried using a .for_each() instead of for ... and it went down to 24 lines of asm.

Is there some deep insight from Clippy that I'm missing? Is there a more idiomatic way of writing this "zero the excess" code?

\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

There's a simpler and more idiomatic solution:

digits[n_digits..].fill(0);

You could also do:

for d in &mut digits [n_digits..MAX_DIGITS] {
    *d = 0;
}

However, these work slightly differently then your original. If n_digits is > MAX_DIGITS, the slice versions will panic on the slice. But your original version will do nothing, because the range is considered empty.

\$\endgroup\$
1
  • \$\begingroup\$ Brilliant! I did not know about .fill()! \$\endgroup\$ Aug 24, 2022 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.