mirror of
https://github.com/qemu/qemu.git
synced 2025-08-16 14:54:29 +00:00
rust: qom: remove operations on &mut
The dubious casts of mutable references to objects are not used anymore: the wrappers for qdev_init_clock_in and for IRQ and MMIO initialization can be called directly on the subclasses, without casts, plus they take a shared reference so they can just use "upcast()" instead of "upcast_mut()". Remove them. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
5778ce9997
commit
094cd35913
@ -175,11 +175,6 @@ pub fn init_io<T: IsA<Object>>(
|
|||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
Self::do_init_io(
|
Self::do_init_io(
|
||||||
// self.0.as_mut_ptr() needed because Rust tries to call
|
|
||||||
// ObjectDeref::as_mut_ptr() on "&mut Self", instead of coercing
|
|
||||||
// to "&Self" and then calling MemoryRegion::as_mut_ptr().
|
|
||||||
// Revisit if/when ObjectCastMut is not needed anymore; it is
|
|
||||||
// only used in a couple places for initialization.
|
|
||||||
self.0.as_mut_ptr(),
|
self.0.as_mut_ptr(),
|
||||||
owner.cast::<Object>(),
|
owner.cast::<Object>(),
|
||||||
&ops.0,
|
&ops.0,
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
pub use crate::qom::IsA;
|
pub use crate::qom::IsA;
|
||||||
pub use crate::qom::Object;
|
pub use crate::qom::Object;
|
||||||
pub use crate::qom::ObjectCast;
|
pub use crate::qom::ObjectCast;
|
||||||
pub use crate::qom::ObjectCastMut;
|
|
||||||
pub use crate::qom::ObjectDeref;
|
pub use crate::qom::ObjectDeref;
|
||||||
pub use crate::qom::ObjectClassMethods;
|
pub use crate::qom::ObjectClassMethods;
|
||||||
pub use crate::qom::ObjectMethods;
|
pub use crate::qom::ObjectMethods;
|
||||||
|
@ -463,90 +463,7 @@ unsafe fn unsafe_cast<'a, U: ObjectType>(self) -> &'a U
|
|||||||
impl<T: ObjectType> ObjectDeref for &T {}
|
impl<T: ObjectType> ObjectDeref for &T {}
|
||||||
impl<T: ObjectType> ObjectCast for &T {}
|
impl<T: ObjectType> ObjectCast for &T {}
|
||||||
|
|
||||||
/// Trait for mutable type casting operations in the QOM hierarchy.
|
|
||||||
///
|
|
||||||
/// This trait provides the mutable counterparts to [`ObjectCast`]'s conversion
|
|
||||||
/// functions. Unlike `ObjectCast`, this trait returns `Result` for fallible
|
|
||||||
/// conversions to preserve the original smart pointer if the cast fails. This
|
|
||||||
/// is necessary because mutable references cannot be copied, so a failed cast
|
|
||||||
/// must return ownership of the original reference. For example:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// let mut dev = get_device();
|
|
||||||
/// // If this fails, we need the original `dev` back to try something else
|
|
||||||
/// match dev.dynamic_cast_mut::<FooDevice>() {
|
|
||||||
/// Ok(foodev) => /* use foodev */,
|
|
||||||
/// Err(dev) => /* still have ownership of dev */
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait ObjectCastMut: Sized + ObjectDeref + DerefMut
|
|
||||||
where
|
|
||||||
Self::Target: ObjectType,
|
|
||||||
{
|
|
||||||
/// Safely convert from a derived type to one of its parent types.
|
|
||||||
///
|
|
||||||
/// This is always safe; the [`IsA`] trait provides static verification
|
|
||||||
/// that `Self` dereferences to `U` or a child of `U`.
|
|
||||||
fn upcast_mut<'a, U: ObjectType>(self) -> &'a mut U
|
|
||||||
where
|
|
||||||
Self::Target: IsA<U>,
|
|
||||||
Self: 'a,
|
|
||||||
{
|
|
||||||
// SAFETY: soundness is declared via IsA<U>, which is an unsafe trait
|
|
||||||
unsafe { self.unsafe_cast_mut::<U>() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to convert to a derived type.
|
|
||||||
///
|
|
||||||
/// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if the
|
|
||||||
/// object if the conversion failed. This is verified at runtime by
|
|
||||||
/// checking the object's type information.
|
|
||||||
fn downcast_mut<'a, U: IsA<Self::Target>>(self) -> Result<&'a mut U, Self>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
{
|
|
||||||
self.dynamic_cast_mut::<U>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to convert between any two types in the QOM hierarchy.
|
|
||||||
///
|
|
||||||
/// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if the
|
|
||||||
/// object if the conversion failed. This is verified at runtime by
|
|
||||||
/// checking the object's type information.
|
|
||||||
fn dynamic_cast_mut<'a, U: ObjectType>(self) -> Result<&'a mut U, Self>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
// SAFETY: upcasting to Object is always valid, and the
|
|
||||||
// return type is either NULL or the argument itself
|
|
||||||
let result: *mut U =
|
|
||||||
object_dynamic_cast(self.as_object_mut_ptr(), U::TYPE_NAME.as_ptr()).cast();
|
|
||||||
|
|
||||||
result.as_mut().ok_or(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert to any QOM type without verification.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// What safety? You need to know yourself that the cast is correct; only
|
|
||||||
/// use when performance is paramount. It is still better than a raw
|
|
||||||
/// pointer `cast()`, which does not even check that you remain in the
|
|
||||||
/// realm of QOM `ObjectType`s.
|
|
||||||
///
|
|
||||||
/// `unsafe_cast::<Object>()` is always safe.
|
|
||||||
unsafe fn unsafe_cast_mut<'a, U: ObjectType>(self) -> &'a mut U
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
{
|
|
||||||
unsafe { &mut *self.as_mut_ptr::<Self::Target>().cast::<U>() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ObjectType> ObjectDeref for &mut T {}
|
impl<T: ObjectType> ObjectDeref for &mut T {}
|
||||||
impl<T: ObjectType> ObjectCastMut for &mut T {}
|
|
||||||
|
|
||||||
/// Trait a type must implement to be registered with QEMU.
|
/// Trait a type must implement to be registered with QEMU.
|
||||||
pub trait ObjectImpl: ObjectType + IsA<Object> {
|
pub trait ObjectImpl: ObjectType + IsA<Object> {
|
||||||
|
@ -2,13 +2,10 @@
|
|||||||
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
use std::{
|
use std::{ffi::CStr, ptr::addr_of};
|
||||||
ffi::{c_void, CStr},
|
|
||||||
ptr::{addr_of, addr_of_mut},
|
|
||||||
};
|
|
||||||
|
|
||||||
use qemu_api::{
|
use qemu_api::{
|
||||||
bindings::{module_call_init, module_init_type, object_new, object_unref, qdev_prop_bool},
|
bindings::{module_call_init, module_init_type, qdev_prop_bool},
|
||||||
c_str,
|
c_str,
|
||||||
cell::{self, BqlCell},
|
cell::{self, BqlCell},
|
||||||
declare_properties, define_property,
|
declare_properties, define_property,
|
||||||
@ -182,30 +179,3 @@ fn test_cast() {
|
|||||||
assert_eq!(addr_of!(*sbd_ref), p_ptr.cast());
|
assert_eq!(addr_of!(*sbd_ref), p_ptr.cast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(clippy::shadow_unrelated)]
|
|
||||||
/// Test casts on mutable references.
|
|
||||||
fn test_cast_mut() {
|
|
||||||
init_qom();
|
|
||||||
let p: *mut DummyState = unsafe { object_new(DummyState::TYPE_NAME.as_ptr()).cast() };
|
|
||||||
|
|
||||||
let p_ref: &mut DummyState = unsafe { &mut *p };
|
|
||||||
let obj_ref: &mut Object = p_ref.upcast_mut();
|
|
||||||
assert_eq!(addr_of_mut!(*obj_ref), p.cast());
|
|
||||||
|
|
||||||
let sbd_ref: Result<&mut SysBusDevice, &mut Object> = obj_ref.dynamic_cast_mut();
|
|
||||||
let obj_ref = sbd_ref.unwrap_err();
|
|
||||||
|
|
||||||
let dev_ref: Result<&mut DeviceState, &mut Object> = obj_ref.downcast_mut();
|
|
||||||
let dev_ref = dev_ref.unwrap();
|
|
||||||
assert_eq!(addr_of_mut!(*dev_ref), p.cast());
|
|
||||||
|
|
||||||
// SAFETY: the cast is wrong, but the value is only used for comparison
|
|
||||||
unsafe {
|
|
||||||
let sbd_ref: &mut SysBusDevice = obj_ref.unsafe_cast_mut();
|
|
||||||
assert_eq!(addr_of_mut!(*sbd_ref), p.cast());
|
|
||||||
|
|
||||||
object_unref(p_ref.as_object_mut_ptr().cast::<c_void>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user