I'm defining a macro that defines other macros like this:
macros.rs
#[macro_export]
macro_rules! m1 {
() => {
#[macro_export]
macro_rules! m2 {
() => {}
}
}
}
m1!();
m2!(); // no problem;
I can use m2!
in another crate by use {{crate_name}}::macros::*
, and I can use m2!
in macros.rs
, but I don't know how to use m2!
in files that are in the same crate.
lib.rs
#[macro_use]
pub mod macros;
pub mod test;
pub mod test2;
test.rs (in the same crate as macros.rs)
use crate::m1; // no problem
use crate::m2; // ERROR: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
m1!(); // no problem
m2!(); // error, no m2
test2.rs
use crate::*;
m2!(); // this works, but I don't really want to use crate::*
examples/yo.rs
use {{crate_name}}::m2;
m2!(); // no problem
What is the correct way to use that m2
macro in other files in the same crate? I'm using Rust 1.31.1.
We use a dollar sign ( $ ) to declare a variable in the macro system that will contain the Rust code matching the pattern. The dollar sign makes it clear this is a macro variable as opposed to a regular Rust variable.
Rust has two types of macros: Declarative macros sometimes referred to as "macros by example", “ macro_rules! macros,” or just plain “macros”. Declarative macros enable you to write something similar to a match expression that operates on the Rust code you provide as arguments.
I'm reading a book about Rust, and start playing with Rust macros. All metavariable types are explained there and have examples, except the last one – tt . According to the book, it is a “a single token tree”.
macros can be exported from the current crate using #[macro_export] . Note that this ignores all visibility.
Read and follow the compiler's instructions:
error[E0659]: `m2` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
--> src/lib.rs:22:5
|
22 | m2!();
| ^^ ambiguous name
|
note: `m2` could refer to the macro defined here
--> src/lib.rs:7:13
|
7 | / macro_rules! m2 {
8 | | () => {};
9 | | }
| |_____________^
...
21 | m1!();
| ------ in this macro invocation
note: `m2` could also refer to the macro defined here
--> src/lib.rs:7:13
|
7 | / macro_rules! m2 {
8 | | () => {};
9 | | }
| |_____________^
...
13 | m1!();
| ------ in this macro invocation
error: a macro named `m2` has already been exported
--> src/lib.rs:7:13
|
7 | / macro_rules! m2 {
8 | | () => {};
9 | | }
| |_____________^ `m2` already exported
...
21 | m1!();
| ------ in this macro invocation
|
= note: #[deny(duplicate_macro_exports)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #35896 <https://github.com/rust-lang/rust/issues/35896>
note: previous macro export is now shadowed
--> src/lib.rs:7:13
|
7 | / macro_rules! m2 {
8 | | () => {};
9 | | }
| |_____________^
...
13 | m1!();
| ------ in this macro invocation
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
--> src/lib.rs:19:9
|
19 | use crate::m2;
| ^^^^^^^^^
|
= note: #[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
note: the macro is defined here
--> src/lib.rs:7:13
|
7 | / macro_rules! m2 {
8 | | () => {};
9 | | }
| |_____________^
...
21 | m1!();
| ------ in this macro invocation
Specifically:
error: macro-expanded
macro_export
macros from the current crate cannot be referred to by absolute paths
Applied:
m1
; doing so creates a second m2
.test.rs
// use crate::m1;
// use crate::m2;
// m1!();
m2!();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With