This is related to this issue.
Context
I am the author of sosecrets-rs and right now, I am writing RTSecret<T, MEC: typenum::Unsigned>, which represents a secret that would return an Err or panics only if the value of its internal counter (a counter that measures the number of time a secret is exposed, I name it as ec) exceeds the runtime unsigned integer value represented by the type parameter MEC.
In this issue, @2e71828 helped me to write a declarative macro, named, impl_choose_int!(...) which in a brute force manner, implements the trait like so:
trait ChooseInt {
type Output;
}
to all type level unsigned integers representable by 1 to 64 bits.
Question
The runtime secret struct RTSecret looks like so:
struct RTSecret<
T,
MEC: ChooseInt + typenum::Unsigned,
>(T, std::cell::Cell<<MEC as ChooseInt>::Output>);
The intent is for <MEC as ChooseInt>::Output to give u8 if U1 <= MEC <= U255, u16 if MEC <= U65535 and so on; so that RTSecret can 'save' space.
However, to my shock, Playground, RTSecret<i32, U1000> is the same size as RTSecret<i32, U10>, whereas I would expect the latter to be smaller according to std::mem::size_of.
I understand the algorithm of size_of takes into account of alignment, e.g. i32 is 4 bytes, where <U10 as ChooseInt>::Output = u8 is 1 byte, but because of alignment, 3 bytes are padded so that it is 8 bytes altogether.
However, does it really mean that the layout at runtime is going to also be 8 bytes? If so, then this optimization will be a big waste.