I wanted a way to create an array with non-copy values. So I came up with the following:
use proc_macro::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, Expr, LitInt, Token};
struct ArrayLit(Expr, LitInt);
impl Parse for ArrayLit {
fn parse(input: ParseStream) -> Result<Self> {
let v: Expr = input.parse()?;
let _ = input.parse::<Token![;]>()?;
let n: LitInt = input.parse()?;
Ok(ArrayLit(v, n))
}
}
#[proc_macro]
pub fn arr(input: TokenStream) -> TokenStream {
let arr = parse_macro_input!(input as ArrayLit);
let items = std::iter::repeat(arr.0).take(
arr.1.base10_parse::<usize>().expect("error parsing array length"),
);
(quote! { [#(#items),*] }).into()
}
This works with numeric literal sizes, like:
fn f() -> [Option<u32>; 10] {
let mut it = 0..5;
arr![it.next(); 10]
}
How do I change this proc-macro code so that it will take a const generic? For example, I'd like it to work with the following function:
fn f<const N: usize>() -> [Option<u32>; N] {
let mut it = 0..5;
arr![it.next(); N]
}