Множество примеров, которые я видел, предполагают, что это должно быть возможно, но это, очевидно, не так:
lib.rs
:
#![feature(trace_macros)]
#[macro_export]
macro_rules! inner_macro (
(f32) => {"float"};
);
#[macro_export]
macro_rules! outer_macro {
($T:ty) => {
inner_macro!($T)
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_nested() {
trace_macros!(true);
s1: String = String::from(outer_macro!(f32));
s2: String = String::from(inner_macro!(f32));
trace_macros!(false);
}
}
Запуск cargo test
дает следующий вывод:
error: no rules expected the token `f32`
--> src/lib.rs:11:22
|
4 | / macro_rules! inner_macro (
5 | | (f32) => {"float"};
6 | | );
| |__- when calling this macro
...
11 | inner_macro!($T)
| ^^ no rules expected the token `f32`
...
21 | s1: String = String::from(outer_macro!(f32));
| ----------------- in this macro invocation
Это сбивает с толку, потому что, безусловно, существует правило, ожидающее токен f32
.
Есть также примечания из трассировки расширения двух макросов.Первый не работает:
= note: expanding `outer_macro! { f32 }`
= note: to `inner_macro ! ( f32 )`
= note: expanding `inner_macro! { f32 }`
, а второй работает:
= note: expanding `inner_macro! { f32 }`
= note: to `"float"`
Почему первое расширение inner_macro!
терпит неудачу, в то время как точно такое же расширениеуспешно, если он не вложен в другой макрос?
Редактировать: если мы выполняем замену вручную, она работает и дает ожидаемый результат:
macro_rules! unknown {
($T:ty) => {
inner_macro!(f32)
}
}