#rust #rust-macros
#Ржавчина #rust-макросы
Вопрос:
Рассмотрим следующий фрагмент кода
#[macro_export]
macro_rules! test {
($a:literal) => { $a };
($a:expr) => { $a };
}
fn func() {
let a = test!(0);
let b = test!(a);
let c = test!(-a);
}
Почему третье задание не работает? По какой-то причине из-за -
(я думаю) сбоя в первой макро-ветви. Я бы ожидал, что он будет использовать второе. Почему это не так?
Я получаю следующее сообщение об ошибке:
error: unexpected token: `a`
--> src/gate.rs:144:20
|
137 | ($a:literal) => { $a };
| ---------- while parsing argument for this `literal` macro fragment
...
144 | let c = test!(-a);
| ^
Редактировать: добавление круглых скобок вокруг -a
действительно заставляет его работать, хотя затем он выдает предупреждение:
warning: unnecessary parentheses around assigned value
--> src/gate.rs:144:19
|
144 | let c = test!((-a));
| ^^^^ help: remove these parentheses
|
= note: `#[warn(unused_parens)]` on by default
Комментарии:
1. Это всего лишь догадка: анализатор входит в
literal
ветку, потому что символ «-» совпадает как токен для литерала (например, «-5»); затем он попадает в ловушку, потому что «a» не может быть частью любого литерала, начинающегося с «-«; он не оценивает другие ветвиперед ошибкой. Круглые скобки заставляютexpression
брать ветку, потому что круглые скобки не являются частью какого-либо литерала.2. Это действительно странно, для меня это похоже на ошибку. Я мог бы предложить открыть проблему в репозитории GitHub.
3. Глядя на документы, это действительно похоже на ошибку, поскольку «Обратите внимание, что синтаксис Rust рассматривает -1i8 как применение унарного оператора минус к целочисленному литералу 1i8, а не к одному целочисленному литералу». Я открою проблему
4. См. Проблему