Open bruceg opened 4 months ago
the default code generation/linkage results in there being separate registries in both the module and the loading code
This is the actual thing to fix. I don't think you will be able to solve the issue by messing with TypetagRegistration.
It might be sufficient to have your trait defined in its own shared library, which each of the components dynamically links against. There would be a single registry determined by the shared library containing the trait.
I don't have a lot of experience with Cargo's implementation of shared linkage, other than a general understanding that it is not well-exercised by the ecosystem and I am not certain whether it is expressive enough for this.
I do have experience with using shared linkage for Rust with Buck2. My work codebase has many uses of inventory
with shared linkage that we build using Buck2 and "link groups", including one use of typetag
.
I am experimenting with dynamic loading of components into Vector using dynamic-plugin (which uses
libloading
under the hood FWIW). Those components are configured usingtypetag::serde
on a configuration trait. I have the dynamic loading of the code working, as well as registering items withinventory
(see below). The next part is trying to deserialize a struct in the loaded module throughtypetag::serde
where the trait exists outside of the loaded module.Based on the solution to registration with
inventory
that I worked up, I need to be able to pass (return) the concrete value that is being submitted there from the plugin to the loading code. That value is the return value fromfn <dyn Trait>::typetag_register
. However, that value namesTypetagRegistration
which is hidden in code generated by the proc macro within aconst _: () = { … }
block and so cannot be named outside of that block.~Since that type is effectively the same for all instances of the generated code, would it make any sense to move
TypetagRegistration
intotypetag::__private
likeStrictest
andDeserializeFn
are? I would be happy to submit a PR if you are open to that.~ That won't work because of needing to do animpl
on that type which falls afoul of Rust's orphan rules.Alternately, I am open to any other solution to the
inventory
registration issue. I know that the constructor it generates is actually run when the module is loaded (at least on Linux), but the default code generation/linkage results in there being separate registries in both the module and the loading code. Hypothetically working around that would also resolve the problem, but the best shot I had at it requires differentrustflags
in different crates in the workspace, to which I have not found a solution.