Как сопоставить границы черт в макросе?
Я пытаюсь сопоставить границы признаков для универсальных типов:
macro_rules! test {
(
where $(
$bounded_type:ident: $( $bound:tt )++,
)+
) => {
// Dummy expansion for test:
struct Foo<T, U>
where $(
$bounded_type : $( $bound )++,
)+
{
t: T,
u: U
}
}
}
test! {
where
T: PartialEq + Clone,
U: PartialEq,
}
fn main() {}
К сожалению, если я хорошо понимаю, единственный способ сопоставить черту tt
фрагмент, но этот фрагмент может соответствовать практически чему угодно, поэтому, что бы я ни делал, я получаю ошибку:
error: local ambiguity: multiple parsing options: built-in NTs tt ('bound') or 1 other option.
Как я могу сопоставить этот кусок кода?
Обратите внимание, что мне не нужно что-то очень элегантное (мне это не нужно для любителей plublic), но, конечно, чем элегантнее, тем лучше.
2 ответа
Лучше всего прочитать исходный код parse-generics-shim
ящик; Это немного стар, но, надеюсь, все еще работает. Это слишком запутанно, чтобы объяснить в вопросе переполнения стека, так как в основном это означает копирование + вставка источника этого ящика в ответ.
Более простой подход состоит в том, чтобы просто не анализировать фактический синтаксис Rust и использовать то, что может обработать синтаксический анализатор макросов, например, обернуть ограничения в группу (например, { ... }
).
Я смог сделать так, чтобы это соответствовало, отделяя первую границу от остальных.
macro_rules! test {
(
where $(
$bounded_type:ident: $bound:tt $(+ $others:tt )*,
)+
) => {
// Dummy expansion for test:
struct Foo<T, U>
where $(
$bounded_type : $bound $(+ $others)*,
)+
{
t: T,
u: U
}
}
}
Однако это не сработает, если у черт есть параметры.
Примерно в 2016 году с закрытием этого номера вы можете использовать path
тип макроса для соответствия TypePath
s.
Например, из моего собственного кода:
($name:ident<$($l:lifetime, )*$($x:ident : $xt:path),+>($s:ident$(, $a:ident: $t:ty)*) -> $ret:ty => $body:block) => {
}