rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
10.89k stars 1.46k forks source link

`clippy::cast_possible_truncation` is inconsistent in recognizing where values will never be truncated #12721

Closed MATSMACKE closed 2 weeks ago

MATSMACKE commented 2 weeks ago

Summary

In some expressions, the lint recognizes that the u16 that is being casted to u8 will always be a valid u8 but in other expressions it does not. I'm not sure whether this is just a limitation of the algorithm used to check for valid u8 internally or an actual bug, but even if it is a limitation of the algorithm it could be useful to others to expand the capabilities of the lint.

Lint Name

cast_possible_truncation

Reproducer

I tried this code:

self.emit_byte((0x00_ff & val) as u8);

I saw this happen:

warning: casting `u16` to `u8` may truncate the value
   --> codegen/src/lib.rs:277:24
    |
277 |         self.emit_byte((0x00_ff & val) as u8);
    |                        ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation
    = note: `-W clippy::cast-possible-truncation` implied by `-W clippy::pedantic`
    = help: to override `-W clippy::pedantic` add `#[allow(clippy::cast_possible_truncation)]`
help: ... or use `try_from` and handle the error accordingly
    |
277 |         self.emit_byte(u8::try_from(0x00_ff & val));
    |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~

I expected to see this happen: This clearly will never be an invalid u8, since the & operation with 0x00_ff means only the last 8 bits can be nonzero. Interestingly, a similar case where a value is bitshifted does result in the lint not triggering, so maybe it's possible to also do that for cases like this.

Where lint works correctly:

self.emit_byte(((0xff_00 & val) >> 8) as u8);

Version

rustc 1.77.0 (aedd173a2 2024-03-17)
binary: rustc
commit-hash: aedd173a2c086e558c2b66d3743b344f977621a7
commit-date: 2024-03-17
host: aarch64-apple-darwin
release: 1.77.0
LLVM version: 17.0.6

Additional Labels

No response