Re: [PATCH v2 1/6] rust: io: turn IoCapable into a functional trait

Danilo Krummrich
2026-02-16T17:04:43Z

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().