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:
Red Bear OS
2026-06-29 19:36:06 +03:00
parent 7ad5ef4e97
commit 10b3ab9713
+40
View File
@@ -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 ()>;
}