-
Notifications
You must be signed in to change notification settings - Fork 51
Add draft of variadic notes #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
6ce73d2
Add draft of variadic notes
CraftSpider fc4d6c4
Fix typos
CraftSpider 1cad19c
Rename variadic_design.txt to variadic_design.md
nikomatsakis d7e4ce3
Rename variadic_design.md to variadic_generics_design.md
CraftSpider 5b612ba
Amend some bits per review feedback
Mark-Simulacrum File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have |
||
- 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<Head, Tail> MyTrait for (Head, ...Tail) where Tail: Tuple {} | ||
|
||
fn foo<T: MyTrait>(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 <ARG> @in args <T> { | ||
Vec::<Arg>::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. | ||
|
||
## 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. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eddyb also has previously expressed a preference for symmetric VG-- that is, VG, which would allow pulling out the first or last element, rather than fixing the choice of left->right traversal or right->left traversal. I don't know how important I personally feel this is, but it's worth noting given that this was the subject of quite a bit of discussion in previous proposals.