Oh, a bit like inheritance in pure C? Where as long as inheriting struct puts the parent struct as first field, you can pass it to functions that use parent struct because the memory layout rules ensure that this part of memory will be exactly the same in both?
Yes, except rust has even stricter requirements - namely that your struct must only contain the “inherited” field and you still need to tell the rust compiler to use the special #[repr(transparent)]!
This is because the compiler is allowed - under “normal” representation rules - to rearrange basically everything about the memory layout of a struct to better suit its needs. And as far as I know this includes rearranging the location of a field which is arbitrarily deep inside other structures in your struct! As such
structA {
foo: u8,
bar: u8,
}
structB {
test: u8,
nested: A,
}
could theoretically be laid out as bar test foo in memory if the compiler determined that accessing bar at the start of the struct was overall the “best”.
If, on the other hand, you use #[repr(c)] you get exactly what you just said, although the direct casting may or may not be undefined still. (I currently do not remember the relevant parts of the nomicon or other treaties I have read about this… I really need to get back into programming rust at some point!)
Oh, a bit like inheritance in pure C? Where as long as inheriting struct puts the parent struct as first field, you can pass it to functions that use parent struct because the memory layout rules ensure that this part of memory will be exactly the same in both?
Yes, except rust has even stricter requirements - namely that your struct must only contain the “inherited” field and you still need to tell the rust compiler to use the special
#[repr(transparent)]!This is because the compiler is allowed - under “normal” representation rules - to rearrange basically everything about the memory layout of a struct to better suit its needs. And as far as I know this includes rearranging the location of a field which is arbitrarily deep inside other structures in your struct! As such
struct A { foo: u8, bar: u8, } struct B { test: u8, nested: A, }could theoretically be laid out as
bar test fooin memory if the compiler determined that accessing bar at the start of the struct was overall the “best”.If, on the other hand, you use
#[repr(c)]you get exactly what you just said, although the direct casting may or may not be undefined still. (I currently do not remember the relevant parts of the nomicon or other treaties I have read about this… I really need to get back into programming rust at some point!)