Using derive proc-macros in main crate

I have a problem with the layout of proc macro crates. I have a library crate (let's call it foo ), which exports a trait Bar . Ideally, it also provides a derive macro but, since foo also uses declarative macros, I have to create a separate crate for this (let's call it foo-derive ).
Now, the trait Bar is also implemented within foo , so I would like foo to depend on foo-derive so that I can use #[derive(Bar)] in foo . On the other hand, foo-derive uses fully-qualified path names for the types and traits it uses in foo, so for instance it would impl ::foo::Bar for ... { ... } .
This works in any library that depends on foo , but not in foo itself, for which the path should be crate::Bar . Also, I can't make foo-derive publicly re-export the trait Bar in foo so that I can use ::foo_derive::Bar instead, because then I would have a circular dependency between foo and foo-derive . Is there a way to solve this (ie. provide derive macros for everyone)?

Here is an answer to your question that I've written in a different topic, hope that helps you:

1 Like

also, see the discussion in this issue

1 Like

The extern crate self as foo Just Works for me, however it's:

  • a bit hacky: it's not entirely clear to someone who reads the code why is that even useful in the first place;
  • a bit fragile: I've realized (I knew that but it didn't occur to me) that people can rename the dependency foo (or even not have it at all), and it will completely break the code.

However, while reading the discussion linked by @nerditation, I found a reference to the proc-macro-crate crate, which solves all these issues. Given the name of the crate foo, it will fetch in Cargo.toml whether this crate is a dependency (or is the current crate), and in this case, provide the actual name (ie. after renaming) or crate if it's the current crate. This doesn't seem to be reliable if there is no Cargo.toml but, at this point, there is nothing more I can do I think.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.