@@ -7,7 +7,8 @@
use qemu_api::{
bindings::*,
c_str,
- definitions::ObjectImpl
+ definitions::ObjectImpl,
+ zeroable::Zeroable,
};
use crate::device::PL011State;
@@ -16,7 +17,7 @@
pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
name: PL011State::TYPE_INFO.name,
unmigratable: true,
- ..unsafe { ::core::mem::MaybeUninit::<VMStateDescription>::zeroed().assume_init() }
+ ..Zeroable::ZERO
};
qemu_api::declare_properties! {
@@ -2,11 +2,14 @@
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
-use core::{mem::MaybeUninit, ptr::NonNull};
+use core::ptr::NonNull;
use std::os::raw::{c_uint, c_void};
-use qemu_api::bindings::*;
+use qemu_api::{
+ bindings::*,
+ zeroable::Zeroable
+};
use crate::device::PL011State;
@@ -16,11 +19,11 @@
read_with_attrs: None,
write_with_attrs: None,
endianness: device_endian::DEVICE_NATIVE_ENDIAN,
- valid: unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_1>::zeroed().assume_init() },
+ valid: Zeroable::ZERO,
impl_: MemoryRegionOps__bindgen_ty_2 {
min_access_size: 4,
max_access_size: 4,
- ..unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_2>::zeroed().assume_init() }
+ ..Zeroable::ZERO
},
};
@@ -14,6 +14,7 @@ _qemu_api_rs = static_library(
'src/device_class.rs',
'src/offset_of.rs',
'src/tests.rs',
+ 'src/zeroable.rs',
],
{'.' : bindings_rs},
),
@@ -100,7 +100,7 @@ const fn _calc_prop_len() -> usize {
fn _make_properties() -> [$crate::bindings::Property; PROP_LEN] {
[
$($prop),*,
- unsafe { ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init() },
+ $crate::zeroable::Zeroable::ZERO,
]
}
@@ -125,7 +125,7 @@ macro_rules! vm_state_description {
$vname.as_ptr()
},)*
unmigratable: true,
- ..unsafe { ::core::mem::MaybeUninit::<$crate::bindings::VMStateDescription>::zeroed().assume_init() }
+ ..$crate::zeroable::Zeroable::ZERO
};
}
}
@@ -31,6 +31,7 @@ unsafe impl Sync for bindings::VMStateDescription {}
pub mod definitions;
pub mod device_class;
pub mod offset_of;
+pub mod zeroable;
#[cfg(test)]
mod tests;
new file mode 100644
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+use std::ptr;
+
+/// This trait provides a replacement for core::mem::zeroed() that can be
+/// used as a `const fn` prior to Rust 1.75.0. As an added bonus it removes
+/// usage of `unsafe` blocks.
+///
+/// Unlike other Zeroable traits found in other crates (e.g.
+/// [`pinned_init`](https://docs.rs/pinned-init/latest/pinned_init/trait.Zeroable.html))
+/// this is a safe trait because the value `ZERO` constant has to be written by
+/// hand. The `pinned_init` crate instead makes the trait unsafe, but it
+/// provides a `#[derive(Zeroable)]` macro to define it with compile-time
+/// safety checks. Once we can assume Rust 1.75.0 is available, we could
+/// switch to their idea, and use `core::mem::zeroed()` to provide a blanked
+/// implementation of the `ZERO` constant.
+pub trait Zeroable: Default {
+ const ZERO: Self;
+}
+
+impl Zeroable for crate::bindings::Property__bindgen_ty_1 {
+ const ZERO: Self = Self { i: 0 };
+}
+
+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(),
+ };
+}
+
+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(),
+ };
+}
+
+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,
+ };
+}
+
+impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {
+ const ZERO: Self = Self {
+ min_access_size: 0,
+ max_access_size: 0,
+ unaligned: false,
+ };
+}
MaybeUninit::zeroed() is handy, but it introduces unsafe (and has a pretty heavy syntax in general) and anyway it is not available as a "const" function until Rust 1.75.0. Introduce a trait that provides the same functionality while staying within safe Rust. In the future we may want to add automatic derivation and implementation of the trait, once we can assume Rust 1.75.0; for now the implementation is manual. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/hw/char/pl011/src/device_class.rs | 5 +- rust/hw/char/pl011/src/memory_ops.rs | 11 ++-- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/device_class.rs | 4 +- rust/qemu-api/src/lib.rs | 1 + rust/qemu-api/src/zeroable.rs | 75 ++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 rust/qemu-api/src/zeroable.rs