rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.23k stars 679 forks source link

Clippy warns of useless_transmute in bitfields' setters and getters #2807

Open Jsbjr opened 2 months ago

Jsbjr commented 2 months ago

When using bitfields in clippy warns that the transmute in the new, setter and getter are useless. I don't know if it is a false positive from clippy or if the transmutes are indeed uneeded.

Input C/C++ Header

typedef struct {
    unsigned int a: 1;

} StructWithBitfields;

// Create a default bitfield
StructWithBitfields create_bitfield();

Bindgen Invocation

use std::env;
use std::path::PathBuf;

fn main() {
    let bindings = bindgen::Builder::default()
        .header("header.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

Main user code

mod bitfields {
    #![allow(non_upper_case_globals)]
    #![allow(non_camel_case_types)]
    #![allow(non_snake_case)]
    #![allow(dead_code)]
    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
fn main() {
    let mut bfield = unsafe { bitfields::create_bitfield()};
    bfield.set_a(1);
    println!("a set to {}", bfield.a()); 
}

Actual Results

$ cargo clippy
    Checking test_bindgen v0.1.0 (c:\tmp\test_bindgen)
warning: transmute from a type (`u32`) to itself
   --> C:\tmp\test_bindgen\target\debug\build\test_bindgen-cf2f8ecb2d57bd29\out/bindings.rs:107:18
    |
107 |         unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute
    = note: `#[warn(clippy::useless_transmute)]` on by default

warning: transmute from a type (`u32`) to itself
   --> C:\tmp\test_bindgen\target\debug\build\test_bindgen-cf2f8ecb2d57bd29\out/bindings.rs:112:28
    |
112 |             let val: u32 = ::std::mem::transmute(val);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute

warning: transmute from a type (`u32`) to itself
   --> C:\tmp\test_bindgen\target\debug\build\test_bindgen-cf2f8ecb2d57bd29\out/bindings.rs:120:35
    |
120 |             let a: u32 = unsafe { ::std::mem::transmute(a) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute

warning: `test_bindgen` (bin "test_bindgen") generated 3 warnings
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s

Expected Results

I expect no warnings when using clippy. It is possible to explicitly silence the warning with #![warn(clippy::useless_transmute)] but I would prefer not to silence warnings if possible.

emilio commented 2 months ago

I'd be against making the bitfields code more complicated. We can add the #[allow(clippy::useless_transmute)] on the generated code tho...

Jsbjr commented 2 months ago

I would be happy with this solution. I made these changes here: https://github.com/Jsbjr/rust-bindgen/tree/allow-transmute and it seems to work fine. Should I make a PR?