Есть ли способ "сделать макрос вещи" в атрибуте без процедурного макроса?

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

/// foo
///
#[doc="bar\n\nbaz"]
///
/// quux
struct Dummy;

Следующим шагом будет замена этой строки моим контентом. По этому я не могу написать #[doc=my_content!()]и макросы атрибутов являются процедурными, поэтому для этого мне нужен еще один ящик, плюс (я думаю) мой контент может быть сгенерирован без необходимости каких-либо процедурных макрокомпонентов.

Есть ли способ сделать это с "обычными макросами" каким-то образом, или мне не повезло?

1 ответ

Решение

Ответ, кажется, нет.

Если посмотреть на грамматику атрибутов, то, кроме скобок, запятых и знаков равенства, атрибуты могут в конечном итоге содержать только литералы. Таким образом, на этом уровне Rust не позволяет больше.


Тем не менее, инвертирование структуры позволяет что-то вроде этого, и doc-commentклеть делает это для комментариев к документу. Вместо вызова макроса из атрибута используйте макрос для создания атрибута; этот макрос не ограничивается только получением литералов *. Недостатком является то, что элемент, к которому должен применяться атрибут, должен быть частью вызова макроса. Так это

#[doc=my_content!()]
struct Foo;

становится таким:

doc_comment!(
    my_content!(),
    struct Foo;
);

Определение макроса просто:

#[macro_export]
macro_rules! doc_comment {
    ($x:expr, $($tt:tt)*) => {
        #[doc = $x]
        $($tt)*
    };
}

(опущена ветвь исходного макроса, которая не является частью основной структуры)

(спасибо Йонасу-Шлевинку за указание на это)


* за исключением этой последней части (получение макрокоманды в атрибут), ответ на связанный вопрос уже делает именно это.

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