Crate foo_derive implements a derive macro for MyTrait. In order to refer to the types/traits in foo, foo_deriveuses it with ::foo::*. All code generated by the macro (including uses) is wrapped in a const _: () = { ... }; to avoid polluting the caller's scope.
This has worked fine for using the macro from a third crate, but now I want to use it from crate foo lest I have to implement the trait manually. Is this possible? Simply using it ends up throwing the following error:
error[E0463]: can't find crate for `foo`
--> crates/foo/src/my_trait.rs:10:10
|
10 | #[derive(MyTrait)]
| ^^^^^^^ can't find crate
|
= note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info)
I assume this means I can only refer to foo as crate when I'm inside it, but the macro can't tell the difference. Is there a standard/recommended way of performing these imports in generated code?
You can write extern crate self as foo; in the lib.rs of your foo crate precisely for this reason
Aside: try not to use use … "statements" in your proc-macro code, since you may still be clashing with what your caller provided:
A generic parameter may be called like your trait:
struct Example<MyTrait> {
field: MyTrait,
}
Good luck writing impl<MyTrait> MyTrait for Example<MyTrait>
Some proc-macros need to mention the type of the field in the emitted code (e.g., <#FieldType as MyTrait>::…).
In that case, you may clash with #FieldType being some type called MyTrait, or the caller of your derive having, themselves, defined some trait MyTrait, and then having #FieldType = Box<dyn MyTrait>.
If you have a use ::foo::*; then if the caller had a MyTrait of their own in scope, you won't be implementing your trait but theirs; if you have a use ::foo::MyTrait;, then you won't be correctly mentioning the actual #FieldType but rather the type Box<dyn ::foo::MyTrait> instead.
TL,DR: avoid use … "statements" as much as possible among your emitted code, and instead, write maximally full paths whenever possible