I believe I've already found a workaround by just matching against the finite number of concrete types and passing the syn::type struct into the function manually, but it would be nice not to have to do that. I was wondering if anyone knew of a way I could do something like this:
fn some_proc_macro_helper<T>(...) -> proc_macro2::TokenStream {
let parsed_type = /* something akin to syn::parse(T) */
let some_ident = ...;
let val = ...;
TokenStream::from(quote!{
let #some_ident : #parsed_type = ...
})
}
I'm not sure I understand your question, but do you mean something like quote::ToTokens(), but for types instead of values?
for example, it might look like this:
// a trait for type based dispatch
trait TypeToTokens {
fn to_tokens(tokens: &mut TokenStream);
}
// an adapter for the `ToTokens` trait so you can use in `quote!{ ... }`
struct TypeToTokensHelper<T: TypeToTokens>(PhantomData<T>);
impl<T: TypeToTokens> ToTokens for TypeToTokensHelper<T> {
fn to_tokens(&self, tokens: &mut TokenStream) {
<T as TypeToTokens>::to_tokens(tokens)
}
}
/// example usage:
fn declare_variable<T: TypeToTokens>(name: &str, val: ...) -> TokenStream {
let name = format_ident!("{}", name);
let ty = TypeToTokensHelper::<T>::new();
quote! {
let #name : #ty = #val;
}
}
let foo_decl = declare_variable::<u32>("foo", ...);
let bar_decl = declare_variable::<Box<str>>("bar", ...);
it can be implemented for the types you need, for example:
/// for builtin types
impl TypeToTokens for u32 {
fn to_tokens(tokens: &mut TokenStream) {
tokens.append(Ident::new("u32", Span::call_site());
}
}
/// for standard library types
impl<T: TypeToTokens + ?Sized> TypeToTokens for Box<T> {
fn to_tokens(tokens: &mut tokens) {
let ty = TypeToTokensHelper::<T>::new();
tokens.append_all(quote! { ::std::boxed::Box::< #ty > })
}
}
I think this is exactly what I'd need, I attempted something similar but presumably failed because I was being lazy and was trying to make a solution where I wouldn't need to create an impl for each specific type. But, my workaround involves me making a bunch of match statements dispatching on the type regardless though, so it's better to just do the work once. Thank you for the help