Ошибка макроса при попытке реализовать черту внутри макроса
fn a() {}
кажется, удовлетворяет правилу синтаксического анализа, который ожидал fn
и другие вещи. item
s должен быть в состоянии быть определениями функций, верно? Значит, они должны работать, верно?
macro_rules! multi_impl {
(for $base:ty :
$($t:ty {
$($i:item);*
}),+) =>
{
$(
impl $t for $base
{
$( $i )*
}
)+
}
}
trait A {
fn a();
}
trait B {
fn b();
}
struct S;
multi_impl! {
for S:
A {
fn a() {}
}, B {
fn b() {}
}
}
fn main() {
S::a();
S::b();
}
Ошибка в вопросе:
error: expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `fn a() { }`
--> <anon>:11:20
|
11 | $( $i )*
| ^^
Делая это $( fn $i)*
только изменяет ошибку, чтобы пожаловаться на ожидание идентификатора после fn
, что имеет смысл, но первоначальной ошибки нет (по крайней мере, для меня).
Есть ли разница в синтаксическом анализаторе относительно кода, который находится в исходном коде против кода, который помещается в исходный код макросом?
1 ответ
Проблема не в том, что fn
это не предмет, это то, что тело impl
не содержит предметов Содержит "предметы". На что он жалуется, так это на то, что вы пытаетесь положить квадратный блок в круглое отверстие, а не на то, что блок имеет неправильный цвет.
Да, это две разные вещи. Нет, вы не можете захватить "элементы impl" в макросе. Нет, вы не можете превратить предмет в неявный предмет. Потому что макросы захватывают узлы AST, а не токены. Ну, методы могут иметь self
аргумент и обычная функция не делают. Я не знаю, по-видимому, в то время это казалось хорошей идеей.
Если оставить в стороне гипотетический вопрос, решение в этом случае состоит в том, чтобы не пытаться сопоставить что-либо конкретное и просто сопоставить что-либо.
macro_rules! multi_impl
{
(for $base:ty :
$($t:ty {
$($body:tt)*
}),+) =>
{
$(
impl $t for $base
{
$($body)*
}
)+
}
}