# Variadic generics - pre-RFC

**URL:** <https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619>\
**Category:** language design\
**Created:** [October 19, 2018, 12:34pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619 "2018-10-19T12:34:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 12:34pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/1 "2018-10-19T12:34:26Z")

</div>

I’d love get some feedback on my pre-RFC for variadic generics. 🙂

> <https://github.com/memoryleak47/variadic-generics/blob/master/0000-variadic-generics.md>

This RFC is highly inspired by the draft made by @eddyb ([https://github.com/rust-lang/rfcs/issues/376](https://github.com/rust-lang/rfcs/issues/376)).

---

<div class="post-metadata">

**Author:** ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)\
**Post date:** [October 19, 2018, 1:05pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/2 "2018-10-19T13:05:18Z")

</div>

I had to read it a couple of times to ensure I was getting all the details straight, but, overall it seems like a solid way to handle variadics. I think the syntax is reasonable, but, the “…” syntax might conflict with existing use of “…” as range either actually or at least cognitively.

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [October 19, 2018, 1:55pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/3 "2018-10-19T13:55:59Z")

</div>

For the purposes of facilitating initial review, I would suggest creating a PR against your on repository; I’ll leave some line comments when you do that. 🙂

---

<div class="post-metadata">

**Author:** ![TheDan64](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/thedan64/32/368_2.png) [@TheDan64](https://internals.rust-lang.org/u/TheDan64)\
**Post date:** [October 19, 2018, 2:33pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/4 "2018-10-19T14:33:17Z")

</div>

I really like this approach.

I think you could use some more examples of the `fn foo<*T>` type, for example:

Would you be able to do `fn foo<*T: Debug>(foo: T) { ... }` to specify that tuple T is Debug (and by extension, all elements of the tuple are Debug)? So you could, say, iterate over the tuple and debug-print out each one separately?

What I’d really like to use this for is type parameterizing with variable sized tuples. So, with the above syntax, `fn my_struct_of_tuples<*T: MyTrait>(foo: T) -> MyStruct<T> { ... }` which (I think you’re saying) would be called like `my_struct_of_tuples((1, 2, 3));` and give me a `MyStruct<(i32, i32, i32)>`?

---

<div class="post-metadata">

**Author:** ![TimNN](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/timnn/32/11461_2.png) [@TimNN](https://internals.rust-lang.org/u/TimNN)\
**Post date:** [October 19, 2018, 3:02pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/5 "2018-10-19T15:02:12Z")

</div>

If I understand the proposal correctly, the only way to “iterate” over each element of a variadic tuple is recursion. This seems like a potential downside to me (although having tuples large enough for the recursion limit to become an issue seems somewhat unlikely in normal code).

---

<div class="post-metadata">

**Author:** ![DanCardin](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@DanCardin](https://internals.rust-lang.org/u/DanCardin)\
**Post date:** [October 19, 2018, 3:03pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/6 "2018-10-19T15:03:00Z")

</div>

What’s the idea behind using the two different syntaxes `..` and `*`? because really variadicness is packing, so the operator would pack or unpack depending on the context.

e.g. in python you have `a, *b = c` and `def a(*b):` in both locations. Though i could see `*` being confusing or ambiguous, so would `..` work in such locations that you’re using `*` currently?

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 4:33pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/7 "2018-10-19T16:33:57Z")

</div>

The problem when reusing `..`-syntax is, as follows, `..arg` talks about the elements of the tuple `arg`, and considering a function `fn foo(..arg: (i32;))`, the part `..arg: (i32;)` suggests that the elements of `arg` are of type `(i32;)`. Which is wrong, as the elements are of type `i32`.

Yet I get the point, it’d be a nice symmetry if both things would use the same syntax.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 4:54pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/8 "2018-10-19T16:54:42Z")

</div>

> `(T;T: Clone)`

I don't think we need syntax for handling bounds as part of the type. I think a more robust and way of handling bounds would be something like

```Rust
impl<*T> T
where *T: Clone {
}

```

Where `*T: Clone` means all elements of the tuple type implement `Clone`.

This would also mean that bounds on `T` itself mean bounds on the tuple, which is simpler and more consistent.

* * *

> [@DanCardin](#):
>
> What’s the idea behind using the two different syntaxes `..` and `*` ? because really variadicness is packing, so the operator would pack or unpack depending on the context.

I think that this is worth looking into, I don't think we can use `*` because that could conflict with pointer dereference, and `..` or `...` conflicts with ranges. We could use more dots, `....`, but that seems too long. Maybe we could bring back `~` for this?

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 4:55pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/9 "2018-10-19T16:55:49Z")

</div>

> [@TheDan64](#):
>
> Would you be able to do `fn foo<*T: Debug>(foo: T) { ... }` to specify that tuple T is Debug (and by extension, all elements of the tuple are Debug)? So you could, say, iterate over the tuple and debug-print out each one separately?

Look into the examples, I did exactly that with `Display`.

> [@TheDan64](#):
>
> What I’d really like to use this for is type parameterizing with variable sized tuples. So, with the above syntax, `fn my_struct_of_tuples<*T: MyTrait>(foo: T) -> MyStruct<T> { ... }` which (I think you’re saying) would be called like `my_struct_of_tuples((1, 2, 3));` and give me a `MyStruct<(i32, i32, i32)>` ?

yes.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 4:59pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/10 "2018-10-19T16:59:58Z")

</div>

Also, from the previous discussion of this, it was noted that tuples don’t necessarily contain contiguous parts of memory that would represent a sub-tuple. For example, `(i32, u32, f32)` does not have to have a sub-tuple `(u32, f32)`.

Because of this, how would this be handled.

```rust
let tuple: (i32, u32, f32) = (-1, 0, 2.0);
let (x, ..xs) = &tuple;

```

Specifically, what is the type of `xs`?

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 5:04pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/11 "2018-10-19T17:04:07Z")

</div>

> [@RustyYato](#):
>
> Specifically, what is the type of `xs` ?

See the Destructuring part. `xs` would be of type `(&u32, &f32)`.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 5:07pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/12 "2018-10-19T17:07:07Z")

</div>

Ok, I asked because that’s slightly different because you are passing the tuple by value, not a reference to the tuple. Thanks for the reply.

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 5:17pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/13 "2018-10-19T17:17:44Z")

</div>

> [@RustyYato](#):
>
> Where `*T: Clone` means all elements of the tuple type implement `Clone` .

If I understand correctly you think abstract-tuple-types are not required, because you could also add syntax, which talks about all elements of a tuple. Correct me, if I understood wrong.

Something like this was my initial idea, but how would you eg. define associated types, which have to be tuples? Currently this works with `type A: (T;T);` This is required as otherwise you could never use `..` onto an associated type, as you would not know whether the associated type is a tuple-type.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 5:21pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/14 "2018-10-19T17:21:20Z")

</div>

We don’t have generic associated types yet, and if and when we do get them we will have where bounds on associated types. Therefore, bounds on tuple types could be defined earlier in the impl using where bounds.

```rust
impl<*T> Trait for Foo<T>
where T: Clone {
   type Assoc = T;
}

```

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 5:30pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/15 "2018-10-19T17:30:09Z")

</div>

> [@Centril](#):
>
> For the purposes of facilitating initial review, I would suggest creating a PR against your on repository; I’ll leave some line comments when you do that. 🙂

Do you mean I should create a PR to my own repository?

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 5:38pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/16 "2018-10-19T17:38:24Z")

</div>

Hm… I don’t quite understand. How would you define the following without this syntax?

```
trait Foo {
    type A: (T;T);
}
```

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 5:38pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/17 "2018-10-19T17:38:58Z")

</div>

`(T; T)` isn’t a trait, right? So you can’t use it as a bound.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [October 19, 2018, 5:41pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/18 "2018-10-19T17:41:24Z")

</div>

> [@RustyYato](#):
>
> and `..` or `...` conflicts with ranges.

`...` does not have any conflict with ranges.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [October 19, 2018, 5:42pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/19 "2018-10-19T17:42:45Z")

</div>

`...` is valid in match patterns. [Proof](https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=bebb1aa3524373903f088f140d54523c).

---

<div class="post-metadata">

**Author:** ![memoryleak47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/memoryleak47/32/4831_2.png) [@memoryleak47](https://internals.rust-lang.org/u/memoryleak47)\
**Post date:** [October 19, 2018, 5:45pm UTC](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619/20 "2018-10-19T17:45:34Z")

</div>

I recognize I could have been more explicit about this, but yes `(T; T)` is a trait or shall at least behave like a trait.

[Next page](https://internals.rust-lang.org/t/variadic-generics-pre-rfc/8619.md?page=2)
