0

I would broadly like to write something like this:

pub struct Example<..T> {...}

That is, parametrise Example over any number of type T. This is discussed in an RFC, but this seems to be quite stale.

I know that we can have variadic functions by using c_variadic. Is there any way to expand this to structs?

Edit to include more concrete example:

What I am trying to do is (may not be valid Rust, but just an example):


// `a` and `b` are some structs that communicate via channels
// Label is some label we can match on
// Continuation is a trait

let options = vec![(label1, cont1), (label2, cont2)...];
let a = Offer<...(Label, Continuation)>::new();
let b = Pick<Label>::new();

// offer and pick are just some functions that communicate
// the choice via channels
// The important part being that offer and pick would be parametrised
// over <..(Label, Continuation)>
let picked = a.offer(options);
let picked = b.pick(label1);
Niktivan
  • 16
  • 3
  • It's not currently possible to have variadic type parameters. If you explain what you're trying to do, someone can propose alternatives. – eggyal Oct 21 '22 at 10:26
  • Thanks for the reply, I've added a more (hopefully) concrete example – Niktivan Oct 21 '22 at 10:42
  • Possibly relevant: https://stackoverflow.com/questions/74098839/how-does-wasmtime-handle-import-functions-with-arbitrary-signature#comment130830109_74098839 – Jmb Oct 21 '22 at 12:27

1 Answers1

0

Perhaps you want a const size parameter:

struct Offer<T, const U: usize> {
    contents: [T; U]
}

This can represent a list of any size. All items must be of the same type though but in your example this seems to be the case.

mousetail
  • 7,009
  • 4
  • 25
  • 45
  • 1
    You could set `contents: Option<[T; U]>` then populate it later in a type safe way. I'm still very confused why you think variadic generics would solve your problem, or what your problem even is. – mousetail Oct 21 '22 at 10:54
  • I think perhaps my example was bad. Even without the labels, what I would like is `struct Offer<..T:Continuations)>`. Where `T` can be different `Continuations`. In this sense, the compiler would check which continuations we could pick – Niktivan Oct 21 '22 at 10:59
  • I.e. we could have `Offer` and a function that would be able to operate/return only on these. So if the `pick` function tries to pick e.g. `Cont4` or something that is not one of `Cont1, Cont2, Cont3` this would not compile – Niktivan Oct 21 '22 at 11:00
  • Take a look at bevy for example, they just implement a trait for all tuples upto a given size then use `struct S(); trait Trait{}; impl T for (A); impl Trait for (A,B)` etc. with macros – mousetail Oct 21 '22 at 11:03
  • Indeed, but does this not have the need to implement this boilerplate for any number of parameters I would need? I.e. if I find out I need three I now need a `(A, B, C)` implementation and so on? – Niktivan Oct 21 '22 at 11:04
  • Other libraries do this with macros, so they can just do `impl_trait!(A, B, C)` and thus they can easily expand this to whatever number of parameters they need with minimal code addition. – mousetail Oct 21 '22 at 11:10
  • I'm afraid in my use case I'd run into many of the same issues that people have discussed with macros in the RFC but this does seem like the only likely way to do this for now... I could possibly also do this as an enum with all variants of `Cont`, which is also not ideal. In any case, thanks for pointing me to more examples of the macro way! – Niktivan Oct 21 '22 at 11:22