I have a proc-macro crate with a macro that, when expanded, needs to use custom trait implementations for Rust built-in types. I tried to define the trait in the same crate, but Rust tells me that a proc-macro crate can only have public macros (the functions annotated with #[proc_macro]
) and nothing else can be public. So I put the trait in another crate and in the proc-macro crate included it as a dependency. But this means that anyone that wants to use my proc-macro crate has to depend on the other trait crate too.
So I wonder if there is a way to add a public trait to the proc-macro crate, or otherwise to make the proc-macro and trait crates linked in some way so the end user can't try to use one without the other? If neither is possible, the only solution is documenting the dependency, which is kind of fragile.
The way this is usually dealt with is to not have users depend on your proc-macro crate at all.
Your problem can be solved with 3 crates:
Whenever your macro mentions the shared types in its generated code, you need to use the fully-qualified names so that users don't also need to import them.
Some popular examples of this pattern in the wild:
thiserror
depends on thiserror-impl
which contains the actual macrospin-project
depends on pin-project-internal
which again contains the macrosdarling
depends on darling-core
and darling-macro
, which itself also depends on darling-core