Il ven 18 ott 2024, 05:16 Junjie Mao <junjie....@hotmail.com> ha scritto:

>
> Paolo Bonzini <pbonz...@redhat.com> writes:
>
> > 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.
>
> Agree.
>
> Then how about converting with_offsets! to a derive attribute
> (e.g. #[derive(offsets)])? The current approach introduces one more
> level of indentation. When we later upgrade the minimal supported
> version of Rust and switch to std::mem::offset_of!, we'll need a large
> diff to adjust the indentation which may be annoying to rebase upon. An
> attribute seems easier to manage.
>

Ok, using quote! to generate the with_offsets! {} call should be easy.

Paolo


> I can help draft the macro early next week if you think that is valuable.
>
> Junjie Mao
>
> >
> > 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/
>
>

Reply via email to