diff --git a/src/design_notes/variadic_generics_design.md b/src/design_notes/variadic_generics_design.md new file mode 100644 index 0000000..fe3230f --- /dev/null +++ b/src/design_notes/variadic_generics_design.md @@ -0,0 +1,146 @@ + +# Variadic Generics + +A draft for Variadic Generics has existed since ~2013, and there have been multiple postponed RFCs surrounding +the topic. Despite this, the difficulty of designing such a system as well as lack of singular best choice +has led to no resolution. This document has been written as an attempt to 'sum up' proposals and discussion in +this space. + +# Proposals so far + +Following will be an overview of each of the proposals so far, followed by their individual pros and cons + +## EddyB's Draft + +This is a simple proposal, and the oldest one. It proposes the basic idea that all variadic types can +be seen as just a tuple with N elements. The syntax is thus built around allowing expansions of tuple +types into their components, and taking multiple types that will be condensed into a tuple. + +For using these types, it is proposed that one destructure the tuple, generally into a single head, and the remaining +tail. This matches the recursive style used in C++. There is also some desire to +be able to iterate in both directions (from left or right) rather than fixing +the choice to a single direction. + +### Pros + +- Simple. Doesn't add much syntax while allowing the driving use case, the `Fn` traits and similar designs. + +- Allows intuitive function call ergonomics + +### Cons + +- Mentioned by eddyb, a subtuple type could have different padding than its parent. + EG: `&(A, B, C, D) != &A, &(B, C, D)` + +- The `..` syntax is already used in ranges, so some other syntax would be needed + - Note that `...` syntax may be available, as `..=` is now the inclusive + range syntax. + +### Syntax + +```rust +type Tuple<..T> = T; + +(..(true, false), ..(1, "foo")) == (true, false, 1, "foo") + +fn bar(..x: (A, B, C)) {} +``` + +## Cramertj's Proposal + +Proposes both a syntax similar to C++ as well as a Tuple trait that will be implemented by all tuples. +The trait would contain helpful types and methods for working with variadic tuples: +- AsRefs type, `(A, B, C) -> (&A, &B, &C)` +- AsMuts type, `(A, B, C) -> (&mut A, &mut B, &mut C)` +- elements_as_refs fn, with signature `(&'a self) -> Self::AsRefs<'a>` +- elements_as_mut fn, with signature `(&'a mut self) -> Self::AsMuts<'a>` + +- Not provided, but proposed as future extensions: + - Allowing unpacking tuple types in an argument position, preventing the need to call variadic functions like + `foo((1, 2.0, "3"))` + - Allowing the `...` syntax in generic type position, preventing the need to write traits such as `Fn` like + `Fn<(T1, T2, T3)>` + +### Pros + +- Proposes simple syntax, similar to eddyb proposal + +- Includes Tuple trait, which is helpful for working with variadic arguments + +### Cons + +- None yet. + +### Syntax + +```rust +trait MyTrait: Tuple {} + +impl MyTrait for () {} + +impl
MyTrait for (Head, ...Tail) where Tail: Tuple {} + +fn foo