From 6ce73d281a977dd3dc631306fae9e455fcbee933 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 10 Jan 2021 20:05:17 -0500 Subject: [PATCH 1/5] Add draft of variadic notes --- src/design_notes/variadic_design.txt | 133 +++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/design_notes/variadic_design.txt diff --git a/src/design_notes/variadic_design.txt b/src/design_notes/variadic_design.txt new file mode 100644 index 0000000..618d690 --- /dev/null +++ b/src/design_notes/variadic_design.txt @@ -0,0 +1,133 @@ + +# 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++. + +### 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 + +### 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::AsRefs<'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"))` + - Alowing 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 + +- Overlaps with inclusive range syntax, though it shouldn't actually break any backwards compatibility + +### Syntax + +```rust +trait MyTrait: Tuple {} + +impl MyTrait for () {} + +impl MyTrait for (Head, ...Tail) where Tail: Tuple {} + +fn foo(args: T) {} +``` + +## Fredpointzero's Proposal + +Takes a similar path to previous proposals in terms of syntax, but adds on a lot of ergonomics syntax. +This additional syntax is proposed to allow easier usage of the variadic types, allowing the user to generate +more imperative loops over the variadic type. A lot of the debate on this proposal surrounded the proposed for +loop syntax, as many found it hard to read/comprehend at a glance compared to the rest of the proposed syntax. + +### Pros + +- Ergonomics, this proposal allows more linear usage of variadic types, which the other proposals lack. + +- Power, this proposal allows almost full control over the bounds on variadics, and provides many example + implementations. + +### Cons + +- Complexity, much more new syntax is needed than in the other proposals + +- No way to terminate recursive functions currently, they just won't compile + +### Syntax + +``` +struct Foo<(..T)> +where + ..(T: Debug) +{ + items: (..T) +} + +fn append<(..L), (..R)>(l: (..L), r: (..R)) -> (..L, ..R) { + todo!() +} + +fn foo<(..T)>(args: (..T)) { + let (head, tail @ ..) = args; + + (for arg @in args { + Vec::::new(); + }) +} +``` + +## Common notes + +All the proposals start with a similar syntax, using two or three dots to represent packing/unpacking types. +They all act on tuples, extending language syntax to allow tuples of varrying instead of constant arity, and building +all new functionality on top of that idea. + +The overlap with range is a common topic of discussion, but all full proposals seem to still use that syntax. +Overall, the basic syntax seems to be agreed on, but usability and 'extra' ergonomic functionality still requires +a lot of work. From fc4d6c4a1e7665cbdb6216daac3151261af02971 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 27 Jan 2021 17:42:40 -0500 Subject: [PATCH 2/5] Fix typos --- src/design_notes/variadic_design.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/design_notes/variadic_design.txt b/src/design_notes/variadic_design.txt index 618d690..f874eea 100644 --- a/src/design_notes/variadic_design.txt +++ b/src/design_notes/variadic_design.txt @@ -49,12 +49,12 @@ The trait would contain helpful types and methods for working with variadic tupl - 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::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"))` - - Alowing the `...` syntax in generic type position, preventing the need to write traits such as `Fn` like + - Allowing the `...` syntax in generic type position, preventing the need to write traits such as `Fn` like `Fn<(T1, T2, T3)>` ### Pros From 1cad19ccccf9508482c1bfe7cfdea822c8c63e1f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 2 Jun 2021 13:54:24 -0400 Subject: [PATCH 3/5] Rename variadic_design.txt to variadic_design.md --- src/design_notes/{variadic_design.txt => variadic_design.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/design_notes/{variadic_design.txt => variadic_design.md} (100%) diff --git a/src/design_notes/variadic_design.txt b/src/design_notes/variadic_design.md similarity index 100% rename from src/design_notes/variadic_design.txt rename to src/design_notes/variadic_design.md From d7e4ce3fc1b2070953b080c9571bb609c0bd5378 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 2 Jun 2021 21:11:58 -0400 Subject: [PATCH 4/5] Rename variadic_design.md to variadic_generics_design.md --- .../{variadic_design.md => variadic_generics_design.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/design_notes/{variadic_design.md => variadic_generics_design.md} (100%) diff --git a/src/design_notes/variadic_design.md b/src/design_notes/variadic_generics_design.md similarity index 100% rename from src/design_notes/variadic_design.md rename to src/design_notes/variadic_generics_design.md From 5b612ba1994981e1c9680700abcf2cc5e12993cb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 26 Oct 2021 14:15:19 -0400 Subject: [PATCH 5/5] Amend some bits per review feedback --- src/design_notes/variadic_generics_design.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/design_notes/variadic_generics_design.md b/src/design_notes/variadic_generics_design.md index f874eea..fe3230f 100644 --- a/src/design_notes/variadic_generics_design.md +++ b/src/design_notes/variadic_generics_design.md @@ -17,7 +17,9 @@ be seen as just a tuple with N elements. The syntax is thus built around allowin 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++. +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 @@ -28,9 +30,11 @@ tail. This matches the recursive style used in C++. ### Cons - Mentioned by eddyb, a subtuple type could have different padding than its parent. - EG: `&(A, B, C, D) != &A, &(B, C, D)` + 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 @@ -65,7 +69,7 @@ The trait would contain helpful types and methods for working with variadic tupl ### Cons -- Overlaps with inclusive range syntax, though it shouldn't actually break any backwards compatibility +- None yet. ### Syntax @@ -131,3 +135,12 @@ all new functionality on top of that idea. The overlap with range is a common topic of discussion, but all full proposals seem to still use that syntax. Overall, the basic syntax seems to be agreed on, but usability and 'extra' ergonomic functionality still requires a lot of work. + +## Tuple layout + +Another important consideration for these proposals, particularly those resting +on tuples, is the layout of the tuple. We do not currently guarantee any +particular ordering of the fields in a tuple, which can limit our ability to +"subset" the tuple under a reference. See [this +comment](https://github.com/rust-lang/lang-team/pull/76#issuecomment-857206830) +for some discussion.