Unexpected "macro is ambiguous" error when macro imports are generated by a macro
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
This code compiles just fine, as one would expect:
macro_rules! assert_biteq_rt {
($left:expr, $right:expr $(,)?) => {};
}
macro_rules! assert_biteq_const {
($left:expr, $right:expr $(,)?) => {};
}
// Use the runtime version by default.
// This way, they can be shadowed by the const versions.
pub(crate) use assert_biteq_rt as assert_biteq;
// Also make the const version available for re-exports.
pub(crate) use assert_biteq_const;
mod something_nomacro {
use super::*;
mod const_ {
use super::*;
use crate::assert_biteq_const as assert_biteq;
#[test]
pub fn test() {
const { assert_biteq!(0, 0); }
}
}
}
However, if I write a macro to generate the actual module at the end that contains the test...
macro_rules! float_test {
(
name: $name:ident,
test $test:block
) => {
mod $name {
use super::*;
mod const_ {
use super::*;
use crate::assert_biteq_const as assert_biteq;
#[test]
fn test() {
const { $test }
}
}
}
}
}
float_test! {
name: something_macro,
test {
assert_biteq!(0, 0);
}
}
... then it stops compiling:
error[E0659]: `assert_biteq` is ambiguous
--> src/lib.rs:53:9
|
53 | assert_biteq!(0, 0);
| ^^^^^^^^^^^^ ambiguous name
|
= note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
note: `assert_biteq` could refer to the macro imported here
--> src/lib.rs:39:21
|
39 | use crate::assert_biteq_const as assert_biteq;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
50 | / float_test! {
51 | | name: something_macro,
52 | | test {
53 | | assert_biteq!(0, 0);
54 | | }
55 | | }
| |_- in this macro invocation
= help: use `self::assert_biteq` to refer to this macro unambiguously
note: `assert_biteq` could also refer to the macro imported here
--> src/lib.rs:38:21
|
38 | use super::*;
| ^^^^^^^^
...
50 | / float_test! {
51 | | name: something_macro,
52 | | test {
53 | | assert_biteq!(0, 0);
54 | | }
55 | | }
| |_- in this macro invocation
= help: consider adding an explicit import of `assert_biteq` to disambiguate
The error helpfully tells me to add an explicit import, but I already did that.
This is a minimized version of real code from the libcore test suite. The only way I found so far to avoid this problem is to avoid use super::*; inside mod const_ and instead manually re-import everything we need. That's quite annoying as it means every time we add a new top-level import, we have to remember to also import it inside mod const_ or else the macro-generated tests will start failing.
Cc @petrochenkov in the hopes that you have an idea of what is going on. It is quite puzzling to me that manually expanding the float_test! macro makes the error go away...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimized Rust example in the issue, then compare it with library/coretests/tests/floats/mod.rs. Reproduce the ambiguity and compare manual expansion with float_test! expansion, focusing on the interaction between use super::* and the explicit macro import. Done means the generated tests compile without manually re-importing every top-level name, with a regression test covering the behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100