rust-lang / rust-lang/rust-bindgen

Add an option to generate layout tests in a different file.

Open
#1,655 33 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement help wanted
Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Replying to https://github.com/rust-lang/rust-bindgen/issues/1651#issuecomment-545394605 as a new issue


My initial comment was "these generated tests sure don't seem to actually be useful" and then I was asked for an explanation.

So, I guess it depends on who these tests are for.

let's look at an example

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SDL_AssertData {
  pub always_ignore: winapi::ctypes::c_int,
  pub trigger_count: winapi::ctypes::c_uint,
  pub condition: *const winapi::ctypes::c_char,
  pub filename: *const winapi::ctypes::c_char,
  pub linenum: winapi::ctypes::c_int,
  pub function: *const winapi::ctypes::c_char,
  pub next: *const SDL_AssertData,
}
#[test]
fn bindgen_test_layout_SDL_AssertData() {
  assert_eq!(
    ::core::mem::size_of::<SDL_AssertData>(),
    48usize,
    concat!("Size of: ", stringify!(SDL_AssertData))
  );
  assert_eq!(
    ::core::mem::align_of::<SDL_AssertData>(),
    8usize,
    concat!("Alignment of ", stringify!(SDL_AssertData))
  );
  assert_eq!(
    unsafe { &(*(::core::ptr::null::<SDL_AssertData>())).always_ignore as *const _ as usize },
    0usize,
    concat!(
      "Offset of field: ",
      stringify!(SDL_AssertData),
      "::",
      stringify!(always_ignore)
    )
  );
  // and it goes on and on for all the other fields.
}

(We're ignoring the "derefing a null pointer" UB, which the other issue covers, we have to ask ourselves what these tests are intended to check.)

So the Rust types have defined widths and alignments, but the C types are implemented as aliases and they theoretically vary by platform (c_int isn't necessarily always i32, it just usually is).

Now maybe it's a useful thing to have a test where we assert the sizes we expect for the C types based on the local C types when we generated the bindings. You might care to know that the bindings were generated on one machine where C was like "x" and now you're on a machine where C is like "y".

If we do want to check that the local C environment is the same as the one bindgen saw when it ran, we should do that via a single test once at the top of the module:

#[test]
fn test_local_c_env_matches_bindgen_c_env(){
  // assert stuff here
}

We should not have tests per field per struct spread all across the module basically asserting that 2+2 is 4 for thousands of lines.

On the other hand, it's entirely possible that you don't care that the target C environment doesn't match the C environment at the time of running bindgen, because you expected that, and all the structs are defined in terms of the ctype aliases so with the local aliases they've already been corrected to the proper sizes. In this scenario, the current test suite system of being per field is also still mostly useless, since if you have just a single test_local_c_env_matches_bindgen_c_env function that tells you about the changes too.

Either way, we don't need to have size, alignment, and field offset tests per struct. I can't see what scenario that it's guarding against that having a single test of the local ctypes doesn't solve.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the code that generates per-struct layout tests and how generated bindings are assembled. Compare the proposed separate-file option with the existing layout-test output, then verify that the generated bindings contain the requested test placement without changing unrelated generated code.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.