Как импортировать/использовать макрос из другого модуля в одном ящике?

Сценарий реальной жизни:

Я хотел использовать crate::app::verbose_trace!("string literal") внутри crate::app::args::parse модуля.

Воспроизводимый сценарий:

После часа попыток я пришел со следующим простым примером. Это показывает мое непонимание макросов.

  #[macro_use]
  mod foo{
      pub fn bar(){
          println!("bar works")
      }
      #[macro_export]
      macro_rules! baz{
          ()=> {println!("baz works")}
      }
  }

  fn main(){
      foo::bar();
      foo::baz!();
      // Following doesn't work either:
      // use foo::baz;
      // baz!();
  }

Компилятор жалуется

  error[E0433]: failed to resolve: could not find `baz` in `foo`
  --> src\main.rs:14:14
  |
  14 |         foo::baz!();
  |              ^^^ could not find `baz` in `foo`

как будто совсем ослеп :0

Я читаю:
Я хотел бы посмотреть:
  • Компилируемая версия моего примера.
  • Объяснения, почему это не удалось скомпилировать.
  • По выбору:
    • Некоторые другие предложения по использованию marco в подмодуле/супермодуле.
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
0
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

#[macro_export] экспортирует макрос в корень ящика. Таким образом, crate::baz!() будет работать, а foo::baz!() — нет (и #[macro_use] вам не нужен, он для использования макроса в другом крейте).

Если вы хотите экспортировать макрос по этому пути, для локальных макросов ящика не используйте #[macro_export] как все. Вместо этого экспортируйте макрос, например:

macro_rules! baz {
    () => {
        println!("baz works")
    };
}
pub(crate) use baz;

Для экспорта макроса для использования в других крейтах вам еще понадобится #[macro_export]:

#[macro_export]
macro_rules! baz {
    () => {
        println!("baz works")
    };
}
pub use baz;

Это экспортирует макрос как под корень ящика, так и под foo.

есть ли способ избежать экспорта из корня ящика, но экспортировать из текущего модуля таким образом, чтобы его могли использовать другие ящики? У меня есть сценарий, в котором экспорт в корень ящика вызовет конфликты между несколькими модулями.

Sam Johnson 26.01.2023 17:33

@SamJohnson К сожалению, не с macro_rules (только с макросами 2.0). Но вы можете использовать хитрость: экспортировать макрос с искаженным именем #[doc(hidden)] (например, module__macro), а затем повторно экспортировать его с публичным именем из модуля.

Chayim Friedman 26.01.2023 17:38

@SamJohnson Например, #[macro_export] #[doc(hidden)] macro_rules! foo__bar { ... } pub use foo_bar as bar;.

Chayim Friedman 26.01.2023 17:40

Другие вопросы по теме