dtolnay / seq-macro

Macro to repeat sequentially indexed copies of a fragment of code
Apache License 2.0
137 stars 5 forks source link

Can't be used in array initialization #24

Closed theaddonn closed 2 months ago

theaddonn commented 2 months ago

Here is my simple example of what I tried to accomplish: (For the context this is used in a macro to automatically implement serialization of slices, here being the deserialize function)

let buf = [
   seq!(N in 0..$size {
      T::proto_deserialize(stream)?,
   })
];

Weellllllll turns out this code will always generate one expression...

This really should be fixed, I had no way of getting it working with the macro and my current solution is a bit cheaty:

let mut buf: [MaybeUninit<T>; $size] = MaybeUninit::uninit().assume_init();

seq!(N in 0..$size {
   buf[N] = MaybeUninit::new(T::proto_deserialize(stream)?);
});

let buf = unsafe { std::mem::transmute::<_, [T; $size]>(buf) };

also, thanks for this crate :) couldn't be bothered with writing my own macro which does the exact same thing with less features...

theaddonn commented 2 months ago

update, this does work.. but I'm still curious if the above is a bug...

seq!(N in 0..$size {
   let buf = [
      #(
          T::proto_deserialize(stream)?,
      )*
   ];
});
dtolnay commented 2 months ago

This is the correct behavior. T::proto_deserialize(stream)?, T::proto_deserialize(stream)?, is not valid Rust syntax (expression, statement, item, pattern, type) so you are not going to be able to make a macro that expands to it.