Il mer 18 dic 2024, 07:39 Zhao Liu <zhao1....@intel.com> ha scritto: > I supposed a case, where there is such a QOM (QEMU Object Model) > structure relationship: > > * DummyState / DummyClass: defined in Rust side, and registered the > TypeInfo by `Object` macro. > > - So its class_init will be called by C QOM code. > > * DummyChildState / DummyChildClass: defined in Rust side as the > child-object of DummyState, and registered the TypeInfo by `Object` > macro. And suppose it can inherit the trait of DummyClass - > ClassInitImpl<DummyClass> (but I found a gap here, as detailed later; > I expect it should be able to inherit normally). > > - So its class_init will be called by C QOM code. In C code call chain, > its parent's class_init should be called by C before its own > class_init. > - However, note that according to the Rust class initialization call > chain, it should also call the parent's class_init within its own > class_init. > - :( the parent's class_init gets called twice. >
No, I don't think so. You have the same thing already with PL011State/PL011Luminary. There, you have * object_class_init * device_class_init * sysbus_device_class_init * <PL011State as ClassInitImpl<PL011Class>>::class_init * <PL011State as ClassInitImpl<SysBusDeviceClass>>::class_init * <PL011State as ClassInitImpl<DeviceClass>>::class_init * <PL011State as ClassInitImpl<ObjectClass>>::class_init * <PL011Luminary as ClassInitImpl<PL011Class>>::class_init * <PL011Luminary as ClassInitImpl<SysBusDeviceClass>>::class_init * <PL011Luminary as ClassInitImpl<DeviceClass>>::class_init * <PL011Luminary as ClassInitImpl<ObjectClass>>::class_init But note that these calls are all different and indeed the last three are empty (all vtable entries are None). This is like a C class_init implementation that does not set any of sdc, dc or oc. Moving on to another topic, about the gap (or question :-)) where a > child class inherits the ClassInitImpl trait from the parent, please see > my test case example below: Doing something similar to SysBusDevice and > DeviceState using a generic T outside of the QOM library would violate > the orphan rule. > Ugh, you're right. Maybe ClassInitImpl should just be merged into ObjectImpl etc. as a default method implementation. I will check. > > But, when there is deeper class inheritance, it seems impossible to > > > prevent class_init from being called both by the C side's QOM code and > by > > > this kind of recursive case on the Rust side. > > > > > > > Note that here you have two parameters: what class is being filled (the > > argument C of ClassInitImpl<C>) *and* what type is being initialized > > (that's Self). > > > > The "recursion" is only on the argument C, and matches the way C code > > implements class_init. > > For Rust side, PL011Class' class_init calls SysBusDeviceClass' class_init, > and SysBusDeviceClass will also call DeviceClass' class_init. So this is > also recursion, right? > No, Self is not PL011Class. Self is PL011State (or PL011Luminary/ and it always remains the same. What changes is *what part* of the class is overwritten, but the order of calls from qom/object.c follows the same logic in both C and Rust. > Maybe the confusion is because I implemented class_init twice instead of > > using a separate trait "PL011Impl"? > > Ah, yes! But I think the Rust call chain should not use class_init anymore > but should use a different method. This way, the original class_init would > only serve the C QOM. A separate trait might break the inheritance > relationship similar to ClassInitImpl. > Do you still think that this is the case? I will look into how to avoid the problem with the orphan rule, but otherwise I think things are fine. Paolo >