Closed
Description
Hi,
given the following code sample, we read from an MMIO timer that has high and low parts.
If a wrap in low occurred soon after we read it, read the timers again.
extern crate volatile_register;
use volatile_register::RW;
#[repr(C)]
pub struct MMIO {
pub high: RW<u32>,
pub low: RW<u32>,
}
fn main() {
let timer = 0x1337 as *const MMIO;
unsafe {
let mut hi = (*timer).high.read();
let mut lo = (*timer).low.read();
// Repeat if high word changed during read.
if hi != (*timer).high.read() {
hi = (*timer).high.read();
lo = (*timer).low.read();
}
println!("{}", (u64::from(hi) << 32) | u64::from(lo));
}
}
Clippy suggest alternative code in this case.
Checking vcell v0.1.0
Checking volatile-register v0.2.0
Checking volatile_clippy v0.1.0 (file:///home/andre/repos/volatile_clippy)
warning: `if _ { .. } else { .. }` is an expression
--> src/main.rs:16:9
|
16 | / let mut lo = (*timer).low.read();
17 | |
18 | | // Repeat if high word changed during read.
19 | | if hi != (*timer).high.read() {
20 | | hi = (*timer).high.read();
21 | | lo = (*timer).low.read();
22 | | }
| |_________^ help: it is more idiomatic to write: `let <mut> lo = if hi != (*timer).high.read() { ..; (*timer).low.read() } else { (*timer).low.read() };`
|
= note: #[warn(useless_let_if_seq)] on by default
= note: you might not need `mut` at all
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#useless_let_if_seq
Using this suggestion would actually remove the first MMIO read of low. Since volatile instructs the compiler to not reorder volatile operations across each other and/or elide volatile operations, clippy shouldn't do so as well?
I understand this case might be difficult because the volatile hides in an extern crate.