EDIT: Credit to @jswrenn for suggesting a solution: have a particular version of zerocopy depend upon an exact version of zerocopy-derive. This should solve the problem.
I'm the author of zerocopy, which uses the zerocopy-derive proc macro crate to derive impls of some of its traits. I'm working on a refactor that will clean up zerocopy-derive's code and aims to make compilation faster. In particular, I'm trying to factor out some code which is independent of the type that the trait is derived on. Currently, this code is emitted once for every trait impl. I'd like to define this elsewhere in "normal" Rust code rather than in proc-macro-generated Rust code. That will allow me to define it once and then use it in each impl.
I first tried to put it in zerocopy-derive
itself, but apparently that's not supported:
error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
--> src/lib.rs:30:1
|
30 | pub struct Foo;
| ^^^^^^^^^^^^^^^
My next thought was to define it in zerocopy
itself, but this raises a semver problem. Currently, zerocopy
reexports zerocopy-derive
's derive macros, and thus takes a dependency on zerocopy-derive
. This means that zerocopy-derive
cannot also take a dependency on zerocopy
- this would be a dependency cycle, which is disallowed.
Without zerocopy-derive
taking an explicit dependency on zerocopy
, how do I ensure that the crate which uses the derive depends upon a version of zerocopy
which is recent enough that it has the features in question? If an older version of zerocopy
is used, the code emitted by zerocopy-derive
will fail to compile. Complicating matters further, if a newer version of zerocopy
is used which has made a breaking changes to these features, code emitted by zerocopy-derive
will fail to compile.
I genuinely can't figure out whether it's even possible - let alone possible cleanly and without massive headache - to solve the semver problem.
I also considered introducing a third zerocopy-derive-utils
crate which contains the features in question. zerocopy-derive
could then take a dependency on this crate, and semver should sort everything out as normal. This should work, but introduces a third crate, which is pretty suboptimal.
Anyone dealt with anything similar or have any advice?