You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Given a concrete pack substitution, the pattern is repeated for each element in the substituted pack. If `S` is substituted with `Array<Int>, Set<String>`, then `repeat Optional<each S>` will repeat the pattern `Optional<each S>` for each element in the substitution to produce `Optional<Array<Int>>, Optional<Set<String>>`.
@@ -384,20 +385,20 @@ We will refer to `each T` as the _root type parameter pack_ of the member type p
384
385
385
386
### Generic requirements
386
387
387
-
All existing kinds of generic requirements generalize to type parameter packs. Same-type requirements generalize in multiple different ways, depending on whether one or both sides involve a type parameter pack.
388
+
All existing kinds of generic requirements can be used inside _requirement expansions_, which represent a list of zero or more requirements. Requirement expansions are spelled with the `repeat` keyword followed by a generic requirement pattern that captures at least one type parameter pack reference spelled with the `each` keyword. Same-type requirements generalize in multiple different ways, depending on whether one or both sides involve a type parameter pack.
388
389
389
390
1. Conformance, superclass, and layout requirements where the subject type is a type parameter pack are interpreted as constraining each element of the replacement type pack:
A valid substitution for the above might replace `S` with `{Array<Int>, Set<String>}`. Expanding the substitution into the requirement `each S: Sequence` conceptually produces the following conformance requirements: `Array<Int>: Sequence, Set<String>: Sequence`.
396
397
397
-
2. A same-type requirement where one side is a type parameter pack and the other type is a scalar type that does not capture any type parameter packs is interpreted as constraining each element of the replacement type pack to _the same_ scalar type:
398
+
1. A same-type requirement where one side is a type parameter pack and the other type is a scalar type that does not capture any type parameter packs is interpreted as constraining each element of the replacement type pack to _the same_ scalar type:
398
399
399
400
```swift
400
-
funcvariadic<eachS: Sequence, T>(_: repeateach S) where (each S).Element== T {}
401
+
funcvariadic<eachS: Sequence, T>(_: repeateach S) whererepeat(each S).Element== T {}
401
402
```
402
403
403
404
This is called a _same-element requirement_.
@@ -408,7 +409,7 @@ All existing kinds of generic requirements generalize to type parameter packs. S
408
409
3. A same-type requirement where each side is a pattern type that captures at least one type parameter pack is interpreted as expanding the type packs on each side of the requirement, equating each element pair-wise.
409
410
410
411
```swift
411
-
funcvariadic<eachS: Sequence, eachT>(_: repeateach S) where (each S).Element==Array<each T> {}
If both overloads match a given call, e.g. `overload(1)`, the call is ambiguous. Similarly, two generic functions where one accepts a non-pack variadic parameter and the other accepts a type parameter pack:
564
+
If the parameters of the scalar overload have the same or refined requirements as the parameter pack overload, the scalar overload is considered a subtype of the parameter pack overload, because the parameters of the scalar overload can be forwarded to the parameter pack overload. Generally, if a function call successfully type checks with two different overloads, the subtype is preferred. This effectively means that scalar overloads are preferred over parameter pack overloads when the scalar requirements meet the requirements of the parameter pack:
564
565
565
566
```swift
566
-
funcoverload<T>(_: T...) {}
567
+
funcoverload() {}
568
+
funcoverload<T>(_: T) {}
567
569
funcoverload<eachT>(_: repeateach T) {}
568
570
569
-
overload() // ambiguity error
571
+
overload() // calls the no-parameter overload
572
+
573
+
overload(1) // calls the scalar overload
574
+
575
+
overload(1, "") // calls the parameter pack overload
570
576
```
571
577
572
-
In other words, variadic generic functions have the same ranking as other generic functions.
578
+
The general overload subtype ranking rule applies after localized ranking, such as implicit conversions and optional promotions. That remains unchanged with this proposal. For example:
579
+
580
+
```swift
581
+
funcoverload<T>(_: T, _: Any) {}
582
+
funcoverload<eachT>(_: repeateach T) {}
583
+
584
+
overload(1, "") // prefers the parameter pack overload because the scalar overload would require an existential conversion
585
+
```
586
+
587
+
This overload resolution behavior enables library authors to introduce new function overloads using parameter packs that generalize existing fixed-arity overloads while preserving the overload resolution behavior of existing code.
573
588
574
589
## Effect on ABI stability
575
590
@@ -697,7 +712,7 @@ In this proposal, type packs do not have an explicit syntax, and a type pack is
697
712
```swift
698
713
structVariadic<eachT> {}
699
714
700
-
extensionVariadicwhereeachT == {Int, String} {} // {Int, String} is a concrete pack
715
+
extensionVariadicwhere T == {Int, String} {} // {Int, String} is a concrete pack
701
716
```
702
717
703
718
### Pack iteration
@@ -727,7 +742,7 @@ Use cases for variadic generics that break up pack iteration across function cal
727
742
Dynamic pack indexing is useful when the specific type of the element is not known, or when all indices must have the same type, such as for index manipulation or storing an index value. Packs could support subscript calls with an `Int` index, which would return the dynamic type of the pack element directly as the opened underlying type that can be assigned to a local variable with opaque type. Values of this type need to be erased or cast to another type to return an element value from the function:
728
743
729
744
```swift
730
-
funcelement<eachT>(atindex: Int, int: repeateach T)whereeach T:P->any P {
745
+
funcelement<eachT: P>(atindex: Int, int: repeateach T) ->any P {
731
746
// The subscript returns 'some P', which is erased to 'any P'
Changes to the [first reviewed revision](https://github.com/apple/swift-evolution/blob/b6ca38b9eee79650dce925e7aa8443a6a9e5e6ea/proposals/0393-parameter-packs.md):
852
+
853
+
* The `repeat` keyword is required for generic requirement expansions to distinguish requirement expansions from single requirements on an individual pack element nested inside of a pack expansion expression.
854
+
* Overload resolution prefers scalar overloads when the scalar overload is considered a subtype of a parmeter pack overload.
855
+
856
+
834
857
## Acknowledgments
835
858
836
859
Thank you to Robert Widmann for exploring the design space of modeling packs as tuples, and to everyone who participated in earlier design discussions about variadic generics in Swift. Thank you to the many engineers who contributed to the implementation, including Sophia Poirier, Pavel Yaskevich, Nate Chandler, Hamish Knight, and Adrian Prantl.
0 commit comments