This series is logically split in two parts. The first one is more
strictly tied to the objective of splitting qemu_api into multiple crates,
as it breaks the QOM bindings free of the constraints imposed by Rust
orphan rules. The second one instead completes another task that was on
my todo list, namely ensuring that rustc sees the possible changes that
C functions can make when a shared reference &bindings::Foo is passed
via *mut bindings::Foo.
More in detail, patches 1-5 redo the QOM class init mechanism so that
it does not rely on the ClassInitImpl trait. While ClassInitImpl is
very nice in theory, it practice it does not play well with classes
defined outside qemu_api (or more precisely, outside the crate that
defines ClassInitImpl itself). This is because ClassInitImpl relies on
a blanket implementation such as
impl<T> ClassInitImpl<ObjectClass> for T
where
T: ObjectImpl
and this is only possible inside the crate that defines ClassInitImpl.
With these patches the class_init methods move from ClassInitImpl<Class>
to the Class struct itself. More precisely, before the series you
have
<T as ClassInitImpl<ObjectClass>>::class_init
and afterwards
ObjectClass::class_init::<T>
which is assigned to the CLASS_INIT associated const of ObjectImpl.
The problem is that even if CLASS_INIT is always defined the same
way, i.e.
const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
there isn't a way to tell the compiler that the above is valid *in the
definition of ObjectImpl*. Therefore the above line has to be duplicated
in all subclasses; this however is a small issue and in the future it
could be handled by #[derive(Object)].
Patches 6-15 instead introduce a third generic type in qemu_api::cell,
Opaque<T>. This type is similar to a same-named type in Linux; it is
basically a "disable all undefined behavior" switch for the Rust compiler
and it helps maintaining safety at the Rust/C boundary, complementing
the existing BqlCell and BqlRefCell types.
Apart from making things more formally correct, this makes it possible
to implement methods on a struct that is distinct from the one produced
by bindgen. This has a couple of advantages:
- you do not have to disable the Copy trait on structs where you want
to add a Drop trait. This was already a problem for the Timer struct.
- whether Send and Sync are implemented is entirely a decision of the
place that implements the wrapper. Previously, a struct with no
pointers for example would have been always both Send and Sync,
whereas now that can be adjusted depending on the actual
thread-safety of the Rust methods.
- more pertinent to the "multiple crates" plan, you do not have to put
the methods in the same crate as the bindgen-generated bindings.inc.rs.
It also makes Debug output a bit less unwieldy, and in the future one
might want to add specialized implementations of Display and Debug that
are both useful and readable.
Paolo
Paolo Bonzini (15):
rust: add IsA bounds to QOM implementation traits
rust: add SysBusDeviceImpl
rust: qom: add ObjectImpl::CLASS_INIT
rust: pl011, qemu_api tests: do not use ClassInitImpl
rust: qom: get rid of ClassInitImpl
rust: cell: add wrapper for FFI types
rust: qemu_api_macros: add Wrapper derive macro
rust: timer: wrap QEMUTimer with Opaque<>
rust: irq: wrap IRQState with Opaque<>
rust: qom: wrap Object with Opaque<>
rust: qdev: wrap Clock and DeviceState with Opaque<>
rust: sysbus: wrap SysBusDevice with Opaque<>
rust: memory: wrap MemoryRegion with Opaque<>
rust: chardev: wrap Chardev with Opaque<>
rust: bindings: remove more unnecessary Send/Sync impls
docs/devel/rust.rst | 36 +++--
meson.build | 7 -
rust/hw/char/pl011/src/device.rs | 44 +++---
rust/hw/timer/hpet/src/hpet.rs | 7 +-
rust/qemu-api-macros/src/lib.rs | 82 +++++++++++-
rust/qemu-api/meson.build | 7 +-
rust/qemu-api/src/bindings.rs | 26 +---
rust/qemu-api/src/cell.rs | 222 ++++++++++++++++++++++++++++++-
rust/qemu-api/src/chardev.rs | 8 +-
rust/qemu-api/src/irq.rs | 15 ++-
rust/qemu-api/src/memory.rs | 32 ++---
rust/qemu-api/src/qdev.rs | 115 ++++++++++------
rust/qemu-api/src/qom.rs | 203 ++++++++++++++--------------
rust/qemu-api/src/sysbus.rs | 45 ++++---
rust/qemu-api/src/timer.rs | 24 +++-
rust/qemu-api/src/vmstate.rs | 2 +-
rust/qemu-api/tests/tests.rs | 32 ++---
17 files changed, 620 insertions(+), 287 deletions(-)
--
2.48.1