Есть ли согласованный контекст компиляции внутри функции proc_macro_attribute?
Вот пример:
static COUNT: AtomicUsize = AtomicUsize::new(0);
#[proc_macro_attribute]
pub fn count_usages(_attr: TokenStream, item: TokenStream) -> TokenStream {
let c = COUNT.fetch_add(1, Ordering::AcqRel);
println!("Do stuff with c: {}", c);
item
}
Хотя обрабатываемые атрибуты порядка могут отличаться, будет ли окончательный счет каждый раз одинаковым для таких случаев, как:
- Дополнительное строительство
- Ящики реестра и локальные ящики с одной и той же библиотекой и версией proc_macro
- Внутренний параллелизм компилятора
Практический вариант использования (в частности, мой) - создание макета памяти псевдостатических переменных во время компиляции, который будет повторно использоваться в нескольких диспетчерах памяти в статически связанном исполняемом файле.
1 ответ
Хотя некоторые вещи могут работать с текущей реализацией, процедурные макросы не должны использовать глобальные переменные и ожидать, что они будут сохраняться между вызовами.
В настоящее время нет официального механизма для хранения состояния между вызовами процедурного макроса.
Вопрос «Создать локальное состояние для процедурных макросов?»упоминает некоторые из этих моментов:
- Макросы Proc могут не запускаться при каждой компиляции, например, если инкрементная компиляция включена и они находятся в чистом модуле.
- Нет гарантии заказа - если
do_it!
нужны данные со всехconfig!
заклинания, это проблема. - Правильная поддержка этой функции означает добавление нового API.