nvzqz/static-assertions

Feature suggestion: assert_{lt,gt,le,ge}_size

Opened this issue · 2 comments

This would be handy for example to ensure struct sizes don't grow beyond some limit.

It can be implemented like this:

macro_rules! assert_le_size {
    ($a:ty, $b:ty) => {
        const _: MaybeUninit<[u8; size_of::<$b>() - size_of::<$a>()]> = MaybeUninit::uninit();
    }
}

You can already do that with const_assert (since size_of is a const fn), for example:

use std::mem::size_of;

const_assert!(size_of::<u8>() <= size_of::<u16>());

Your proposed implementation wouldn't provide a better/specialized error message, so I don't see why a separate macro for this would be useful.

Here's a macro with a better error message for asserting types are equal:

macro_rules! static_assert_size {
    ($ty:ty, $size:expr) => {
        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    };
}

Before:

error[E0080]: evaluation of constant value failed
  --> lib.rs:62:1
   |
62 | static_assertions::const_assert_eq!(std::mem::size_of::<Settings>(), 0);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
   |
   = note: this error originates in the macro `const_assert` (in Nightly builds, run with -Z macro-backtrace for more info)

After:

error[E0308]: mismatched types
  --> lib.rs:57:32
   |
57 |         const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 0 elements, found one with 160 elements
...
61 | static_assert_size!(Settings, 0);
   | -------------------------------- in this macro invocation
   |
   = note: this error originates in the macro `static_assert_size` (in Nightly builds, run with -Z macro-backtrace for more info)

(this macro is from rustc_data_structures: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/macro.static_assert_size.html)