[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH 1/9] rust: vmstate: add new type safe implementation
From: |
Paolo Bonzini |
Subject: |
Re: [RFC PATCH 1/9] rust: vmstate: add new type safe implementation |
Date: |
Tue, 7 Jan 2025 13:23:50 +0100 |
On Tue, Jan 7, 2025 at 9:39 AM Zhao Liu <zhao1.liu@intel.com> wrote:
> This is very good work! I am curious about how QEMU plays with Rust
> forum:
>
> Rust forum's disscussion is under MIT and Apache 2.0 licenses [1], and
> since vmstate.rs is under the GPLv2 license, do we need to specify that
> certain code retains the MIT license?
I will add a note similar to the one that is already there in offset_of.
> > +/// ```
> > +/// # use qemu_api::call_func_with_field;
> > +/// # use core::marker::PhantomData;
> > +/// const fn size_of_field<T>(_: PhantomData<T>) -> usize {
> > +/// std::mem::size_of::<T>()
> > +/// }
> > +///
> > +/// struct Foo {
> > +/// x: u16,
> > +/// };
> > +/// // calls size_of_field::<u16>()
> > +/// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2);
> > +/// ```
> > +#[macro_export]
> > +macro_rules! call_func_with_field {
> > + ($func:expr, $typ:ty, $($field:tt).+) => {
> > + $func(loop {
> > + #![allow(unreachable_code)]
> > + const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T>
> > { ::core::marker::PhantomData }
> > + // Unreachable code is exempt from checks on uninitialized
> > values.
> > + // Use that trick to infer the type of this PhantomData.
> > + break ::core::marker::PhantomData;
> > + break phantom__(&{ let value__: $typ; value__.$($field).+ });
> > + })
> > + };
> > +}
>
> Very flexible and powerful. (I even think this code could be released as
> a new public crate.)
It's probably not _that_ useful in general, unless you're implementing
this kind of reflection... otherwise I would have found an existing
solution. :) But yes, it's very powerful.
Out of curiosity, I asked claude.ai to explain it and it said "This is
a rather advanced use of Rust's type system and macro capabilities to
do compile-time reflection - basically inspecting the types of struct
fields without runtime overhead. While creative, this pattern isn't
commonly needed in everyday Rust code."
When fed the initial comment from the Rust forum it said "your comment
about wanting to access <T as SomeTrait>::SOMETHING for a field's type
is a classic serialization pattern - often used to get things like
type IDs, serialization formats, or field metadata at compile time".
That's actually pretty impressive; the LLM was also impressed and it
started asking me more about it ("Are you building a custom
serialization framework from scratch, or extending an existing one?").
> > +/// Return the `VMStateField` for a field of a struct. The field must be
> > +/// visible in the current scope.
> > +///
> > +/// In order to support other types, the trait `VMState` must be
> > implemented
> > +/// for them.
> > +#[macro_export]
> > +macro_rules! vmstate_of {
> > + ($struct_name:ty, $field_name:ident $(,)?) => {
>
> why allow a comma at the end? It seems other patches don't use that
> style.
I copied it from the standard library offset_of, but I can remove it too.
> > +// Add a couple builder-style methods to VMStateField, allowing
> > +// easy derivation of VMStateField constants from other types.
> > +impl VMStateField {
> > + #[must_use]
> > + pub const fn with_version_id(mut self, version_id: i32) -> Self {
>
> Why not use u32 (and omit an assert)?
The version_id field is an int in the C struct; you'd still need to
assert that it's <= i32::MAX, and you'd also need an 'as i32'. In
practice it will always be a constant, therefore it will auto-cast to
either i32 or u32.
Paolo