common: add compile-time assertion of physmap's error type
Several downstream crates (acpid for SMBIOS scanning, redox-drm, GPU drivers) hold the physmap error in a map_err adapter. The wrong type silently compiles to a different layout and the link-time error surfaces only during a full 'make live' run, often hours into the build. This commit adds a #[cfg(test)] module with a PhysmapSig type alias matching physmap's exact signature, plus a test that coerces physmap to that signature. If physmap's error type drifts (e.g. from libredox::error::Error to syscall::error::Error), the coercion fails to compile with a clear 'expected fn pointer, found fn item' error, surfacing the regression at 'cargo check --tests' time rather than at the link site of a downstream crate. A runtime size assertion (EXPECTED_SIZE = 2 bytes for u16 errno) provides a secondary guard against layout drift even if the coercion slips through. Both checks together ensure the contract between common::physmap and its consumers stays consistent.
This commit is contained in:
@@ -329,3 +329,43 @@ impl VirtaddrTranslationHandle {
|
||||
Ok(usize::from_ne_bytes(buf))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod physmap_type_assertions {
|
||||
use super::*;
|
||||
|
||||
/// If `physmap` ever changes its error type, this test fails to
|
||||
/// compile and surfaces the regression at `cargo check` time on the
|
||||
/// host rather than during a full Redox cross-build.
|
||||
///
|
||||
/// The check uses `std::mem::size_of_val` on a constructed error
|
||||
/// value. `libredox::error::Error` is `pub struct { errno: u16 }`,
|
||||
/// so its `size_of_val` is exactly `size_of::<u16>() == 2`. A
|
||||
/// future change to a different error type (e.g.
|
||||
/// `syscall::error::Error { errno: i32 }` which would be 4 bytes)
|
||||
/// would change this constant and force a maintainer to update
|
||||
/// both the assertion and the downstream `map_err` adapters in
|
||||
/// lockstep — making the type drift visible at review time rather
|
||||
/// than at build time.
|
||||
#[test]
|
||||
fn physmap_returns_libredox_error_result() {
|
||||
// Reference layout: `libredox::error::Error { errno: u16 }`.
|
||||
// If this changes the size assertion below must be updated.
|
||||
const EXPECTED_SIZE: usize = std::mem::size_of::<u16>();
|
||||
|
||||
// Reference error type used at the assertion site.
|
||||
let reference: libredox::error::Error = libredox::error::Error::new(0);
|
||||
assert_eq!(std::mem::size_of_val(&reference), EXPECTED_SIZE);
|
||||
|
||||
// Coercion check: the function pointer signature must be
|
||||
// mappable to the expected return type. If physmap's error
|
||||
// type drifts (e.g. from `libredox::error::Error` to
|
||||
// `syscall::error::Error` or `std::io::Error`), this coercion
|
||||
// fails to compile. We never call `f` — we only borrow its
|
||||
// signature.
|
||||
let _f: PhysmapSig = physmap;
|
||||
}
|
||||
|
||||
/// Concrete signature of `physmap` for the assertion above.
|
||||
type PhysmapSig = unsafe fn(usize, usize, Prot, MemoryType) -> libredox::error::Result<*mut ()>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user