Skip to content

Commit 094cd35

Browse files
committed
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 <[email protected]>
1 parent 5778ce9 commit 094cd35

File tree

4 files changed

+2
-121
lines changed

4 files changed

+2
-121
lines changed

rust/qemu-api/src/memory.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,6 @@ impl MemoryRegion {
175175
) {
176176
unsafe {
177177
Self::do_init_io(
178-
// self.0.as_mut_ptr() needed because Rust tries to call
179-
// ObjectDeref::as_mut_ptr() on "&mut Self", instead of coercing
180-
// to "&Self" and then calling MemoryRegion::as_mut_ptr().
181-
// Revisit if/when ObjectCastMut is not needed anymore; it is
182-
// only used in a couple places for initialization.
183178
self.0.as_mut_ptr(),
184179
owner.cast::<Object>(),
185180
&ops.0,

rust/qemu-api/src/prelude.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ pub use crate::qom::InterfaceType;
1717
pub use crate::qom::IsA;
1818
pub use crate::qom::Object;
1919
pub use crate::qom::ObjectCast;
20-
pub use crate::qom::ObjectCastMut;
2120
pub use crate::qom::ObjectDeref;
2221
pub use crate::qom::ObjectClassMethods;
2322
pub use crate::qom::ObjectMethods;

rust/qemu-api/src/qom.rs

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -463,90 +463,7 @@ where
463463
impl<T: ObjectType> ObjectDeref for &T {}
464464
impl<T: ObjectType> ObjectCast for &T {}
465465

466-
/// Trait for mutable type casting operations in the QOM hierarchy.
467-
///
468-
/// This trait provides the mutable counterparts to [`ObjectCast`]'s conversion
469-
/// functions. Unlike `ObjectCast`, this trait returns `Result` for fallible
470-
/// conversions to preserve the original smart pointer if the cast fails. This
471-
/// is necessary because mutable references cannot be copied, so a failed cast
472-
/// must return ownership of the original reference. For example:
473-
///
474-
/// ```ignore
475-
/// let mut dev = get_device();
476-
/// // If this fails, we need the original `dev` back to try something else
477-
/// match dev.dynamic_cast_mut::<FooDevice>() {
478-
/// Ok(foodev) => /* use foodev */,
479-
/// Err(dev) => /* still have ownership of dev */
480-
/// }
481-
/// ```
482-
pub trait ObjectCastMut: Sized + ObjectDeref + DerefMut
483-
where
484-
Self::Target: ObjectType,
485-
{
486-
/// Safely convert from a derived type to one of its parent types.
487-
///
488-
/// This is always safe; the [`IsA`] trait provides static verification
489-
/// that `Self` dereferences to `U` or a child of `U`.
490-
fn upcast_mut<'a, U: ObjectType>(self) -> &'a mut U
491-
where
492-
Self::Target: IsA<U>,
493-
Self: 'a,
494-
{
495-
// SAFETY: soundness is declared via IsA<U>, which is an unsafe trait
496-
unsafe { self.unsafe_cast_mut::<U>() }
497-
}
498-
499-
/// Attempt to convert to a derived type.
500-
///
501-
/// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if the
502-
/// object if the conversion failed. This is verified at runtime by
503-
/// checking the object's type information.
504-
fn downcast_mut<'a, U: IsA<Self::Target>>(self) -> Result<&'a mut U, Self>
505-
where
506-
Self: 'a,
507-
{
508-
self.dynamic_cast_mut::<U>()
509-
}
510-
511-
/// Attempt to convert between any two types in the QOM hierarchy.
512-
///
513-
/// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if the
514-
/// object if the conversion failed. This is verified at runtime by
515-
/// checking the object's type information.
516-
fn dynamic_cast_mut<'a, U: ObjectType>(self) -> Result<&'a mut U, Self>
517-
where
518-
Self: 'a,
519-
{
520-
unsafe {
521-
// SAFETY: upcasting to Object is always valid, and the
522-
// return type is either NULL or the argument itself
523-
let result: *mut U =
524-
object_dynamic_cast(self.as_object_mut_ptr(), U::TYPE_NAME.as_ptr()).cast();
525-
526-
result.as_mut().ok_or(self)
527-
}
528-
}
529-
530-
/// Convert to any QOM type without verification.
531-
///
532-
/// # Safety
533-
///
534-
/// What safety? You need to know yourself that the cast is correct; only
535-
/// use when performance is paramount. It is still better than a raw
536-
/// pointer `cast()`, which does not even check that you remain in the
537-
/// realm of QOM `ObjectType`s.
538-
///
539-
/// `unsafe_cast::<Object>()` is always safe.
540-
unsafe fn unsafe_cast_mut<'a, U: ObjectType>(self) -> &'a mut U
541-
where
542-
Self: 'a,
543-
{
544-
unsafe { &mut *self.as_mut_ptr::<Self::Target>().cast::<U>() }
545-
}
546-
}
547-
548466
impl<T: ObjectType> ObjectDeref for &mut T {}
549-
impl<T: ObjectType> ObjectCastMut for &mut T {}
550467

551468
/// Trait a type must implement to be registered with QEMU.
552469
pub trait ObjectImpl: ObjectType + IsA<Object> {

rust/qemu-api/tests/tests.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
// Author(s): Manos Pitsidianakis <[email protected]>
33
// SPDX-License-Identifier: GPL-2.0-or-later
44

5-
use std::{
6-
ffi::{c_void, CStr},
7-
ptr::{addr_of, addr_of_mut},
8-
};
5+
use std::{ffi::CStr, ptr::addr_of};
96

107
use qemu_api::{
11-
bindings::{module_call_init, module_init_type, object_new, object_unref, qdev_prop_bool},
8+
bindings::{module_call_init, module_init_type, qdev_prop_bool},
129
c_str,
1310
cell::{self, BqlCell},
1411
declare_properties, define_property,
@@ -182,30 +179,3 @@ fn test_cast() {
182179
assert_eq!(addr_of!(*sbd_ref), p_ptr.cast());
183180
}
184181
}
185-
186-
#[test]
187-
#[allow(clippy::shadow_unrelated)]
188-
/// Test casts on mutable references.
189-
fn test_cast_mut() {
190-
init_qom();
191-
let p: *mut DummyState = unsafe { object_new(DummyState::TYPE_NAME.as_ptr()).cast() };
192-
193-
let p_ref: &mut DummyState = unsafe { &mut *p };
194-
let obj_ref: &mut Object = p_ref.upcast_mut();
195-
assert_eq!(addr_of_mut!(*obj_ref), p.cast());
196-
197-
let sbd_ref: Result<&mut SysBusDevice, &mut Object> = obj_ref.dynamic_cast_mut();
198-
let obj_ref = sbd_ref.unwrap_err();
199-
200-
let dev_ref: Result<&mut DeviceState, &mut Object> = obj_ref.downcast_mut();
201-
let dev_ref = dev_ref.unwrap();
202-
assert_eq!(addr_of_mut!(*dev_ref), p.cast());
203-
204-
// SAFETY: the cast is wrong, but the value is only used for comparison
205-
unsafe {
206-
let sbd_ref: &mut SysBusDevice = obj_ref.unsafe_cast_mut();
207-
assert_eq!(addr_of_mut!(*sbd_ref), p.cast());
208-
209-
object_unref(p_ref.as_object_mut_ptr().cast::<c_void>());
210-
}
211-
}

0 commit comments

Comments
 (0)