From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org,
Zhao Liu <zhao1.liu@intel.com>
Subject: [PATCH] rust/zeroable: Implement Zeroable with const_zero macro
Date: Fri, 24 Jan 2025 00:31:43 +0800 [thread overview]
Message-ID: <20250123163143.679841-1-zhao1.liu@intel.com> (raw)
`const_zero` crate provides a nice macro to zero type-specific
constants, which doesn't need to enumerates the fields one by one.
Introduce `const_zero` macro to QEMU (along with its documentation), and
use it to simplify the implementation of `Zeroable` trait.
This is valid since current types that require `Zeroable` support can
be safely zeroed using `zero_const`.
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
* Based on the commit d3e2a17bb809 ("rust: qemu-api: add sub-subclass to
the integration tests") of Paolo's rust-next.
---
rust/qemu-api/src/zeroable.rs | 132 +++++++++++++++-------------------
1 file changed, 56 insertions(+), 76 deletions(-)
diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs
index 57cac96de06f..688ee8b059f2 100644
--- a/rust/qemu-api/src/zeroable.rs
+++ b/rust/qemu-api/src/zeroable.rs
@@ -1,13 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-use std::ptr;
-
/// Encapsulates the requirement that
/// `MaybeUninit::<Self>::zeroed().assume_init()` does not cause undefined
/// behavior. This trait in principle could be implemented as just:
///
/// ```
-/// pub unsafe trait Zeroable: Default {
+/// pub unsafe trait Zeroable {
/// const ZERO: Self = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
/// }
/// ```
@@ -29,23 +27,56 @@ pub unsafe trait Zeroable: Default {
const ZERO: Self;
}
-unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {
- const ZERO: Self = Self { i: 0 };
+/// A marco that acts similarly to [`core::mem::zeroed()`], only is const
+///
+/// ## Safety
+/// Similar to `core::mem::zeroed()`, except this zeroes padding bits. Zeroed
+/// padding usually isn't relevant to safety, but might be if a C union is used.
+/// To repeat `core::mem::zeroed()`'s safety, an all zero byte pattern might not
+/// be a valid value for a type; for example, references &T, &mut T.
+///
+/// const_zero does not work on unsized types
+/// ```rust compile_fail
+/// use const_zero::const_zero;
+/// // error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+/// const BYTES: [u8] = unsafe{const_zero!([u8])};
+/// ```
+/// reference types trigger a (denied by default) lint and cause immediate
+/// undefined behavior if the lint is ignored
+/// ```rust compile_fail
+/// use const_zero::const_zero;
+/// // error: any use of this value will cause an error
+/// // note: `#[deny(const_err)]` on by default
+/// const STR: &str = unsafe{const_zero!(&'static str)};
+/// ```
+///
+/// ## Differences with `core::mem::zeroed`
+/// `const_zero` zeroes padding bits, while `core::mem::zeroed` doesn't
+macro_rules! const_zero {
+ // This macro to zero type-specific constants comes from const_zero crate (v0.1.1):
+ //
+ // https://docs.rs/const-zero/latest/src/const_zero/lib.rs.html
+ //
+ // used under MIT license
+ ($type_:ty) => {{
+ const TYPE_SIZE: ::core::primitive::usize = ::core::mem::size_of::<$type_>();
+ union TypeAsBytes {
+ bytes: [::core::primitive::u8; TYPE_SIZE],
+ inner: ::core::mem::ManuallyDrop<$type_>,
+ }
+ const ZERO_BYTES: TypeAsBytes = TypeAsBytes {
+ bytes: [0; TYPE_SIZE],
+ };
+ ::core::mem::ManuallyDrop::<$type_>::into_inner(ZERO_BYTES.inner)
+ }};
}
-unsafe impl Zeroable for crate::bindings::Property {
- const ZERO: Self = Self {
- name: ptr::null(),
- info: ptr::null(),
- offset: 0,
- bitnr: 0,
- bitmask: 0,
- set_default: false,
- defval: Zeroable::ZERO,
- arrayoffset: 0,
- arrayinfo: ptr::null(),
- arrayfieldsize: 0,
- link_type: ptr::null(),
+/// A wrapper to implement `Zeroable` trait by `const_zero` macro.
+macro_rules! impl_zeroable {
+ ($type:ty) => {
+ unsafe impl Zeroable for $type {
+ const ZERO: Self = unsafe { const_zero!($type) };
+ }
};
}
@@ -57,61 +88,10 @@ fn default() -> Self {
}
}
-unsafe impl Zeroable for crate::bindings::VMStateFlags {
- const ZERO: Self = Self(0);
-}
-
-unsafe impl Zeroable for crate::bindings::VMStateField {
- const ZERO: Self = Self {
- name: ptr::null(),
- err_hint: ptr::null(),
- offset: 0,
- size: 0,
- start: 0,
- num: 0,
- num_offset: 0,
- size_offset: 0,
- info: ptr::null(),
- flags: Zeroable::ZERO,
- vmsd: ptr::null(),
- version_id: 0,
- struct_version_id: 0,
- field_exists: None,
- };
-}
-
-unsafe impl Zeroable for crate::bindings::VMStateDescription {
- const ZERO: Self = Self {
- name: ptr::null(),
- unmigratable: false,
- early_setup: false,
- version_id: 0,
- minimum_version_id: 0,
- priority: crate::bindings::MigrationPriority::MIG_PRI_DEFAULT,
- pre_load: None,
- post_load: None,
- pre_save: None,
- post_save: None,
- needed: None,
- dev_unplug_pending: None,
- fields: ptr::null(),
- subsections: ptr::null(),
- };
-}
-
-unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {
- const ZERO: Self = Self {
- min_access_size: 0,
- max_access_size: 0,
- unaligned: false,
- accepts: None,
- };
-}
-
-unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {
- const ZERO: Self = Self {
- min_access_size: 0,
- max_access_size: 0,
- unaligned: false,
- };
-}
+impl_zeroable!(crate::bindings::Property__bindgen_ty_1);
+impl_zeroable!(crate::bindings::Property);
+impl_zeroable!(crate::bindings::VMStateFlags);
+impl_zeroable!(crate::bindings::VMStateField);
+impl_zeroable!(crate::bindings::VMStateDescription);
+impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_1);
+impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_2);
--
2.34.1
reply other threads:[~2025-01-23 16:12 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250123163143.679841-1-zhao1.liu@intel.com \
--to=zhao1.liu@intel.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-rust@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).