我用一个声明性宏嵌套调用其他程序性宏,从arr![1_u32;2]
到arr_proc([1_u32;2])
。我不想直接调用arr_proc!
。但我可能有一些错误,当我编译生 rust 的代码。编译器似乎有时无法展开所有宏。
我的proc宏:
#[proc_macro]
pub fn arr_proc(input: TokenStream) -> TokenStream {
let repeat_expr: ExprRepeat = parse(input)
.expect("Like arr!([Test::default(); 16])");
let mut len = 0;
// get length from repeat_expr
if let Expr::Lit(expr_lit) = repeat_expr.len.deref() {
if let Lit::Int(int_lit) = &expr_lit.lit {
len = int_lit.base10_parse::<usize>().expect("Failed to parse integer literal");
}
}
// parse and concat
let _expr = repeat_expr.expr;
// 1. generate the arr
let mut _all = quote!();
for _i in 0..len {
// 2. append element into arr
_all = quote! { #_all #_expr, };
}
// 3. add []
let arr = quote! { [ #_all ] };
return arr.into();
}
我的声明性宏:
#[macro_export]
macro_rules! arr {
($ele:expr; $repeat:literal) => {
custom_proc_macro::arr_proc!([$ele; $repeat])
};
}
我的测试用例:
#[test]
fn test_arr_() {
let a: [u32; 2] = arr![1_u32;2];
dbg!(a);
}
错误是:
error[E0308]: mismatched types
--> tests/custom_proc_macro_test.rs:48:23
|
48 | let a: [u32; 2] = arr![1_u32;2];
| -------- ^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 0 elements
| | |
| | help: consider specifying the actual array length: `0`
| expected due to this
|
= note: expected array `[u32; 2]`
found array `[_; 0]`
= note: this error originates in the macro `custom_proc_macro::arr_proc` which comes from the expansion of the macro `arr` (in Nightly builds, run with -Z macro-backtrace for more info)
The meaning probably the compiler expanded the declarative macro and did not expand the proc macro.
我怎么能这样用呢?它能工作吗?
1条答案
按热度按时间flvlnr441#
通过使用不带
else
的if-let
,您可以隐藏所有可能的错误条件,这里的特定错误是声明性宏将文字 Package 在未分隔的Group
s中,因此您的if let Expr::Lit(expr_lit) = ...
会默默失败。您仍然可以通过将整个
if-let
语句替换为以下内容来解析它:为了简洁起见,我在这里使用
panic!
,因为Span::error
还不稳定。您可以阅读How to report errors in a procedural macro using the quote macro?来了解如何生成更好的错误消息。但你绝对不能像以前那样,对突发事件视而不见。