Почему proc-макросы должны быть определены в proc-macro crate?

Я пытался создать производный макрос для моей черты, чтобы упростить некоторые вещи.

Я столкнулся с некоторыми проблемами:

the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type

и после небольшого исправления proc-macro=true:

proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate`

В чем причина такого поведения?

1 ответ

Решение

Процедурные макросы в корне отличаются от обычных зависимостей в вашем коде. Нормальная библиотека просто связана с вашим кодом, но процедурный макрос на самом деле является плагином компилятора.

Рассмотрим случай кросс-компиляции: вы работаете на машине с Linux, но создаете проект WASM.

  • Обычный ящик будет кросс-скомпилирован, генерировать код WASM и связываться с остальными ящиками.
  • Ящик proc-macro должен быть скомпилирован нативно, в данном случае с кодом Linux, связан с текущей средой выполнения компилятора (стабильный, бета, ночной) и загружен самим компилятором при компиляции ящиков, где он фактически используется. Он не будет связан с остальными ящиками (другая архитектура!).

А поскольку поток компиляции отличается, тип ящика также должен быть другим, поэтому proc_macro=true необходим.

Об этом ограничении:

proc-macro типы ящиков не могут экспортировать какие-либо предметы, кроме функций, помеченных #[proc_macro_derive]

Итак, поскольку ящик proc-macro загружается компилятором, а не связан с остальными вашими ящиками, любой код не-proc-macro, который вы экспортируете из этого ящика, будет бесполезным.

Обратите внимание, что сообщение об ошибке является неточным, так как вы также можете экспортировать тег функции с помощью #[proc_macro],

И об этом другом ограничении:

функции с тегами #[proc_macro_derive] должен в настоящее время проживать в корне ящика

Добавление proc_macro или же proc_macro_derive элементы во вложенных модулях в настоящее время не поддерживаются и, похоже, не особенно полезны, имхо.

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