I currently have the following sort of architecture:
struct DynamicRustPlugin {
underlying: Box<Trait>
importantHandle: SomeType
}
Specifically, the importantHandle
is some global dynamic library Rust plugin magic that ensures a host dynamic library isn’t closed while the Box<Trait>
is loaded, and only one instance of a given shared object is loaded globally, per program, at a time. The struct itself isn’t really important other than its Drop
and safety-by-existence qualities.
(Specifically, the Rust plugin has a #[no_mangle] new
function that returns a Box<Trait>
of a trait defined in a shared crate and the DynamicRustPlugin
holds this trait object while ensuring the library it came from stays open. I don’t know if this is “officially” supported, but it works perfectly on every platform and build configuration/toolchain I’ve tested on and I’m using copious tests and CI to make sure it doesn’t break).
I have another collection further up that owns a Box<Trait>
as well, since my plugin manager has multiple plugin options such as RPC as well, and for various reasons I can’t use generics, but due to this safety magic, it needs to hold DynamicRustPlugin
as a trait object, not the Box<Trait>
itself.
DynamicRustPlugin
implements Deref<Target=Trait>
and DerefMut<Target=Trait>
and Trait
itself doesn’t take self
by move. It seems that the following rules hold:
* If `Trait` only requires immutable references, and a type implements `Deref<Target=impls Trait>`, it can trivially implement `Trait`
* If `Trait` requires mutable references (but not ownership), and a type implements `Deref<Target=impls Trait>` and `DerefMut`, it can trivially implement `Trait`
(Also, the compiler could, maybe, do magic to prevent two chained virtual function calls by automatically setting the vtable entry for the Box<DerefImplementer as Trait>
to simply its Deref
target’s vtable entry?)
Is there any reason there’s no way to #[derive]
in this case? Are there obvious problems I’m missing? Just too niche of a situation to have been added/be worth adding? The only obvious problem I see is if it’s a common trait such as, e.g., Debug
it would be ambiguous whether #[derive(Debug)]
means the struct itself or the Deref
to a Debug
but there could easily be an attribute like #[derive_deref(Trait)]
that does this.
It’s a bit tiresome implementing each method of a big trait just to do
fn foo(&self) {
self.underlying.foo()
}
Each time.