Re: [PATCH v2 1/6] rust: io: turn IoCapable into a functional trait
From: Danilo Krummrich
Date: Mon Feb 16 2026 - 12:05:01 EST
On Mon Feb 16, 2026 at 2:27 PM CET, Alexandre Courbot wrote:
> It doesn't - here is the implementation of Io for Mmio:
>
> impl<const SIZE: usize> Io for Mmio<SIZE> {
> /// Returns the base address of this mapping.
> #[inline]
> fn addr(&self) -> usize {
> self.0.addr()
> }
>
> /// Returns the maximum size of this mapping.
> #[inline]
> fn maxsize(&self) -> usize {
> self.0.maxsize()
> }
> }
>
> Now what prevents me from doing this:
>
> impl<const SIZE: usize> Io for YoloMmio<SIZE> {
> fn addr(&self) -> usize {
> self.0.addr()
> }
>
> fn maxsize(&self) -> usize {
> self.0.maxsize() + 0x10000
> }
> }
>
> With that, I have allowed callers to invoke the unsafe methods of
> `IoCapable` on an extra 0x10000 bytes of I/O I don't own, without any
> unsafe code.
I don't think you did, as you only present half of your counter example; you
left out the IoCapable part.
I.e. with what you have above cannot uphold the safety justification in the
corresponding IoCapable implementation:
This is the invariant on struct Mmio:
/// # Invariant
///
/// `addr` is the start and `maxsize` the length of valid I/O mapped memory region of size
/// `maxsize`.
And in impl_mmio_io_capable!() you refer to this invariant:
macro_rules! impl_mmio_io_capable {
($mmio:ident, $(#[$attr:meta])* $ty:ty, $read_fn:ident, $write_fn:ident) => {
$(#[$attr])*
impl<const SIZE: usize> IoCapable<$ty> for $mmio<SIZE> {
unsafe fn io_read(&self, address: usize) -> $ty {
// SAFETY: By the trait invariant `address` is a valid address for MMIO operations.
unsafe { bindings::$read_fn(address as *const c_void) }
}
unsafe fn io_write(&self, value: $ty, address: usize) {
// SAFETY: By the trait invariant `address` is a valid address for MMIO operations.
unsafe { bindings::$write_fn(value, address as *mut c_void) }
}
}
};
}
But your YoloMmio implementation doesn't provide this invariant (because it
can't).
So, how do you justify the unsafe call to bindings::$write_fn and
bindings::$read_fn now that you have to call impl_mmio_io_capable!() for
YoloMmio?
Again, you can't justify it, which proves that it doesn't matter what YoloMmio
returns, it matters how you can justify it in io_read() and io_write().