При написании декларативных макросов (macro_rules!
) важно понимать, что вывод макроса должен быть шаблоном, оператором, выражением, элементом или impl
.По сути, вы должны думать о выводе как о чем-то, что может быть автономно, если говорить синтаксически.
В вашем коде макрос f_list
, если бы он работал, вывел бы код наподобие
name1: type1,
name2: type2,
name3: type3,
Хотя это может быть частью объявления для структуры, оно само по себе не может быть чем-то отдельным.
Почему тогда ошибка в другом макросе?mk_str
успешно расширяется до
#[derive(Debug, Clone)]
pub struct Yo {
f_list!(name, String)
}
Однако синтаксический анализатор не ожидает макрос внутри объявления структуры.Внутренняя часть структуры не является шаблоном, оператором, выражением, элементом или impl
.Таким образом, когда он видит !
, он сдается и сообщает об ошибке.
Как вы можете это исправить?В этом конкретном примере f_list
довольно избыточен.Вы можете просто заменить f_list!($fname, $ftype)
на pub $fname: $ftype,
в mk_str
, и все будет работать как написано.Если это не работает для вашей цели, взгляните на Маленькая книга макросов ржавчины .У него есть несколько шаблонов для выполнения очень сложных вещей с макросами.Большая часть информации в этом ответе взята из раздела «Макросы в AST» .