Avoid collecting when passing an iterator of Result<> into quote!

When working with quote, I have code similar to this quite often:

let values = some_iter.map(|x| x.fn_returning_result()).collect::<Result<Box<_>, _>()?;

quote!({
// some stuff omitted
#(#values),*
})

It seems a bit wasteful to allocate a Box here, just to throw it away again immediately after quote! is done. This would work, but panic instead of returning the Err:

let values = some_iter.map(|x| x.fn_returning_result().unwrap());

quote!({
// some stuff omitted
#(#values),*
})

I understand that iterators are lazy and therefore, returning from the let values ... line is not possible for the second example - but is there something that would allow me to do this when playing together with quote?

Why are you allocating a box? What happens when you collect into a Result but do not specify its Ok type?

let values = some_iter.map(|x| x.fn_returning_result()).collect::<Result<_, _>()?;

It doesn't work, see this playground: Rust Playground That's also what I would expect, you need to provide a collection to actually collect into

I see. You want to collect into a Result of iterators, or something like this. But collect() can only be done into a collection that it allocates, and that's a boxed slice Box<[...]> in the OP sample code.

The problem is that ToToken is only implemented on a few primitive types, and Result is not one of them.

Since you are allocating a TokenStream anyway, you can use a loop and "collect" into it by appending tokens while parsing [1]:

let mut quoted = TokenStream::new();
// some stuff omitted
for value in values {
    let value = value?;
    quoted.append_all(quote!(#value,));
}

In other words, use an explicit loop instead of the implicit loop with the #(...)* repetition syntax. Then you can trivially use the ? operator.


  1. This example expects an iterator has been created elsewhere, and it does the parsing internally. You might as well inline the parsing instead, if you can. ↩︎

Hrm, yeah, that would work - it's not the most pretty because there's also a bit of nesting going on etc. I wonder if there even could be another way? Probably not without a change to quote?