The original problem that occurred to us was in strum
crate update. The issue elaborates on the particular case and probably describes the problem in more detail as a good hands-on example.
But, I'll draw the problem in more generic words here.
At the time of this writing, rustc
allows overloading the meaning of symbols if they have the same name in both type and macro namespaces.
This leads to a very hard-to-catch problem, and a caveat each developer should know about.
Suppose a crate mylib
exposes both a trait named Foo
and a proc-macro-derive name Foo
for that trait.
There has been a tendency in the ecosystem that bare proc-macro
crates should be private and their macros should be reexported from the library crate, optionally gated by a cargo feature e.g. cfg(feature = "derive")
.
However, this is restricted neither by the language, nor by cargo
, and it is probably not encouraged by the documentation (but I may be wrong, if it is elaborated somewhere in Rust docs, please share a link). So, the crates like strum
may not be reexporting the proc macros from their library crate, asking the users to depend on the proc-macro
crate directly.
Having this code in upstream crates then leads to a server hazard:
use mylib::Foo;
use mylib_macros::Foo;
Because once mylib
author decides to add pub use mylib_macros::Foo;
to their mylib
crate, they will probably release this change with a compatible minor semver bump. The developer expects the addition of a new symbol to reexports not to break any existing code because they think it's just an API extension.
However, this leads to breakage, because the meaning of use mylib::Foo;
now becomes overloaded and it starts conflicting with use mylib_macros::Foo;
.
This problem is very implicit and probably under-discussed. I don't know how we can solve this problem: either add language-level change to resolve that ambiguity if both paths point to the same symbol or somehow teach every Rust developer of this semver-hazard caveat.
I am really eager to hear the feedback from the Rust team.
Maybe this isn't really a frequent problem, it was just a headache to debug for us, so we are reporting it as feedback.