On Thu, Oct 17, 2024 at 7:35 AM Junjie Mao <junjie....@hotmail.com> wrote: > Paolo Bonzini <pbonz...@redhat.com> writes: > > offset_of! was stabilized in Rust 1.77.0. Use an alternative implemenation > > that was found on the Rust forums, and whose author agreed to license as > > MIT for use in QEMU. > > > > The alternative allows only one level of field access, but apart > > from this can be used just by replacing core::mem::offset_of! with > > qemu_api::offset_of!. > > How about a macro like this (which essentially comes from memoffset > crate [1])? It has the same use as core::mem::offset_of! (except the > same single-level limitation) and does not need wrapping structures with > with_offsets!.
Unfortunately offset_from is not available in const context, and offset_of! is needed to fill in the Property and VMStateDescription arrays. That said, I noticed now that declare_properties! does not declare the resulting array as const, so that would be possible. But if declare_properties could use a non-mut static, that would be better. Paolo > macro_rules! offset_of { > ($parent:ty, $field:tt) => {{ > let uninit = std::mem::MaybeUninit::<$parent>::uninit(); > let base = uninit.as_ptr(); > // SAFETY: > // > // MaybeUninit<$parent> has the same size and alignment as $parent, so > // projection to $field is in bound. > // > // addr_of! does not create intermediate references to the > uninitialized > // memory, thus no UB is involved. > let field = unsafe { std::ptr::addr_of!((*base).$field) }; > // SAFETY: > // > // Both base and field point to the MaybeUninit<$parent> and are > casted > // to u8 for calculating their distance. > unsafe { field.cast::<u8>().offset_from(base.cast::<u8>()) as usize } > }}; > } > > [1] https://docs.rs/memoffset/latest/memoffset/ > > -- > Best Regards > Junjie Mao >