Skip to content

Commit 38612d2

Browse files
authored
Reference for integer generic parameters [SE-0452] (#383)
Fixes: rdar://149983186
2 parents 8d436cd + 0e10385 commit 38612d2

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

TSPL.docc/ReferenceManual/GenericParametersAndArguments.md

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,68 @@ simpleMax(3.14159, 2.71828) // T is inferred to be Double
9999
Tracking bug is <rdar://problem/35301593>
100100
-->
101101

102+
### Integer Generic Parameters
103+
104+
An *integer generic parameter*
105+
acts as a placeholder for an integer value rather than a type.
106+
It has the following form:
107+
108+
```swift
109+
let <#type parameter#>: <#type>
110+
```
111+
112+
The *type* must be the `Int` type from the Swift standard library,
113+
or a type alias or generic type that resolves to `Int`.
114+
115+
The value you provide for an integer generic parameter
116+
must be either an integer literal
117+
or another integer generic parameter from the enclosing generic context.
118+
For example:
119+
120+
```swift
121+
struct SomeStruct<let x: Int> { }
122+
let a: SomeStruct<2> // OK: integer literal
123+
124+
struct AnotherStruct<let x: Int, T, each U> {
125+
let b: SomeStruct<x> // OK: another integer generic parameter
126+
127+
static let c = 42
128+
let d: SomeStruct<c> // Error: Can't use a constant.
129+
130+
let e: SomeStruct<T> // Error: Can't use a generic type parameter.
131+
let f: SomeStruct<U> // Error: Can't use a parameter pack.
132+
}
133+
```
134+
135+
The value of an integer generic parameter on a type
136+
is accessible as a static constant member of that type,
137+
with the same visibility as the type itself.
138+
The value of an integer generic parameter on a function
139+
is accessible as a constant from within the function.
140+
When used in an expression,
141+
these constants have type `Int`.
142+
143+
```swift
144+
print(a.x) // Prints "4"
145+
```
146+
147+
The value of an integer generic parameter can be inferred
148+
from the types of the arguments you use
149+
when initializing the type or calling the function.
150+
151+
```swift
152+
struct AnotherStruct<let y: Int> {
153+
var s: SomeStruct<y>
154+
}
155+
func someFunction<let z: Int>(s: SomeStruct<z>) {
156+
print(z)
157+
}
158+
159+
let s1 = SomeStruct<12>()
160+
let s2 = AnotherStruct(s: s1) // AnotherStruct.y is inferred to be 12.
161+
someFunction(s: s1) // Prints "12"
162+
```
163+
102164
### Generic Where Clauses
103165

104166
You can specify additional requirements on type parameters and their associated types
@@ -124,12 +186,17 @@ specifies that `S` conforms to the `Sequence` protocol
124186
and that the associated type `S.Iterator.Element`
125187
conforms to the `Equatable` protocol.
126188
This constraint ensures that each element of the sequence is equatable.
189+
Integer generic parameters can't have protocol or superclass requirements.
127190

128191
You can also specify the requirement that two types be identical,
129192
using the `==` operator. For example,
130193
`<S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element`
131194
expresses the constraints that `S1` and `S2` conform to the `Sequence` protocol
132195
and that the elements of both sequences must be of the same type.
196+
For integer generic parameters,
197+
the `==` operator specifies a requirement for their values.
198+
You can require two integer generic parameters to have the same value,
199+
or you can require a specific integer value for the integer generic parameter.
133200

134201
Any type argument substituted for a type parameter must
135202
meet all the constraints and requirements placed on the type parameter.
@@ -210,15 +277,17 @@ see <doc:Generics#Generic-Where-Clauses>.
210277
> *generic-parameter-list**generic-parameter* | *generic-parameter* **`,`** *generic-parameter-list* \
211278
> *generic-parameter**type-name* \
212279
> *generic-parameter**type-name* **`:`** *type-identifier* \
213-
> *generic-parameter**type-name* **`:`** *protocol-composition-type*
280+
> *generic-parameter**type-name* **`:`** *protocol-composition-type* \
281+
> *generic-parameter***`let`** *type-name* **`:`** *type* \
214282
>
215283
> *generic-where-clause***`where`** *requirement-list* \
216284
> *requirement-list**requirement* | *requirement* **`,`** *requirement-list* \
217285
> *requirement**conformance-requirement* | *same-type-requirement*
218286
>
219287
> *conformance-requirement**type-identifier* **`:`** *type-identifier* \
220288
> *conformance-requirement**type-identifier* **`:`** *protocol-composition-type* \
221-
> *same-type-requirement**type-identifier* **`==`** *type*
289+
> *same-type-requirement**type-identifier* **`==`** *type* \
290+
> *same-type-requirement**type-identifier* **`==`** *signed-integer-literal*
222291
223292
<!--
224293
NOTE: A conformance requirement can only have one type after the colon,
@@ -239,7 +308,9 @@ and has the following form:
239308

240309
The *generic argument list* is a comma-separated list of type arguments.
241310
A *type argument* is the name of an actual concrete type that replaces
242-
a corresponding type parameter in the generic parameter clause of a generic type.
311+
a corresponding type parameter in the generic parameter clause of a generic type ---
312+
or, for an integer generic parameter,
313+
an integer value that replaces that integer generic parameter.
243314
The result is a specialized version of that generic type.
244315
The example below shows a simplified version of the Swift standard library's
245316
generic dictionary type.
@@ -288,7 +359,7 @@ of a generic function or initializer.
288359
>
289360
> *generic-argument-clause***`<`** *generic-argument-list* **`>`** \
290361
> *generic-argument-list**generic-argument* | *generic-argument* **`,`** *generic-argument-list* \
291-
> *generic-argument**type*
362+
> *generic-argument**type* | *signed-integer-literal*
292363
293364
<!--
294365
This source file is part of the Swift.org open source project

TSPL.docc/ReferenceManual/LexicalStructure.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ in the declaration `let x: Int8 = 42`.
500500
>
501501
> *literal**numeric-literal* | *string-literal* | *regular-expression-literal* | *boolean-literal* | *nil-literal*
502502
>
503-
> *numeric-literal***`-`**_?_ *integer-literal* | **`-`**_?_ *floating-point-literal* \
503+
> *numeric-literal**signed-integer-literal* | *signed-floating-point-literal* \
504504
> *boolean-literal***`true`** | **`false`** \
505505
> *nil-literal***`nil`**
506506
@@ -552,6 +552,7 @@ as described in <doc:TheBasics#Integers>.
552552

553553
> Grammar of an integer literal:
554554
>
555+
> *signed-integer-literal***`-`**_?_ *integer-literal*
555556
> *integer-literal**binary-literal* \
556557
> *integer-literal**octal-literal* \
557558
> *integer-literal**decimal-literal* \
@@ -626,6 +627,7 @@ which represents a 32-bit floating-point number.
626627

627628
> Grammar of a floating-point literal:
628629
>
630+
> *signed-floating-point-literal* → > **`-`**_?_ *floating-point-literal*
629631
> *floating-point-literal**decimal-literal* *decimal-fraction*_?_ *decimal-exponent*_?_ \
630632
> *floating-point-literal**hexadecimal-literal* *hexadecimal-fraction*_?_ *hexadecimal-exponent*
631633
>

0 commit comments

Comments
 (0)