By default no, as for a repr(Rust) struct there's no guarantee on field order nor lack of padding -- so the compiler might have put y at the end of the struct, making that unsound.
You could, however, apply #[repr(C)] to the type to get more guarantees, in which case it becomes possible to do this soundly.
Note that even with #[repr(C)] it still doesn't become sound the way it's done above using &h.y. That reference must not be used to access anything other than the field y.
It's also possible in this example to use existing crates to avoid using unsafe (and thus potentially unsound) code. E. g. bytemuck - Rust
I'm guessing what you are suggesting here is that we should instead be using slice::from_raw_parts(&h, 3) then use [1..] to get the last two elements?
That way we'll only be accessing something inside the memory pointed to by &h and not accessing anything outside the &h.y allocation (assuming #[repr(C)] and so on).
I was actually suggesting to avoid usage of unsafe whenever possible.
On a secondary note, yes, that approach would be sound, except you'll have to cast the *const Holder to *const i32 first. While you're at it, it might be easier to just cast *const Holder to *const [i32; 3] directly.