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
Copy file name to clipboardExpand all lines: docs/ABI/GenericSignature.md
+29-11Lines changed: 29 additions & 11 deletions
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Generic Signatures
2
2
3
3
A generic signature describes a set of generic type parameters along with
4
-
a set of constraints on those type parameters. Generic entities in Swift
4
+
a set of constraints on those parameters. Generic entities in Swift
5
5
have a corresponding generic signature. For example, the following generic function:
6
6
7
7
```swift
@@ -21,9 +21,12 @@ Generic signatures are used in a few places within the ABI, including:
21
21
22
22
* The mangled names of generic entities include the generic signature
23
23
* The generic type parameters and protocol-conformance constraints in a generic signature are mapped to type metadata and witness-table parameters in a generic function, respectively.
24
+
* The entries in a witness table
24
25
25
26
Whenever used in the ABI, a generic signature must be both *minimal* and *canonical*, as defined below.
26
27
28
+
Throughout this document, "type parameter" is used to refer to either a generic type parameter (such as `C1` in the example above) or a nested type rooted at a generic type parameter (such as `C1.Element` or `C1.Iterator.Element`).
29
+
27
30
## Minimization
28
31
29
32
A generic constraint is considered *redundant* if it can be proven true based on some combination of other constraints within the same generic signature. Redundant constraints can be removed from a generic signature without affecting the semantics of the signature. A generic signature is *minimal* when it does not contain any constraints that are redundant.
@@ -55,16 +58,15 @@ Removing both constraints would produce a semantically different generic signatu
55
58
56
59
A generic signature is *canonical* when each of its constraints is [canonical](#canonical-constraints) and the entries in the generic signature appear in canonical order.
57
60
58
-
1. Generic type parameters (that are not nested types) are listed first
61
+
1. Generic type parameters are listed first
59
62
ordered by [type parameter ordering](#type-parameter-ordering)
60
63
2. Constraints follow, ordered first by the
61
64
[type parameter ordering](#type-parameter-ordering) of the left-hand
62
65
operand and then by constraint kind. The left-hand side of a constraint
63
-
is always a type parameter `T`, which can be a generic parameter of a
64
-
nested type thereof (e.g., `T.SubSequence.Iterator.Element`).
66
+
is always a type parameter (call it `T`).
65
67
Constraints are ordered as follows:
66
68
1. A superclass constraint `T: C`, where `C` is a class.
67
-
2. A layout constraints (e.g., `T: some-layout`), where the right-hand
69
+
2. A layout constraint (e.g., `T: some-layout`), where the right-hand
68
70
side is `AnyObject` or one of the non-user-visible layout constraints
69
71
like `_Trivial`.
70
72
3. Conformance constraints `T: P`, where `P` is a protocol. The
@@ -77,13 +79,29 @@ A generic signature is *canonical* when each of its constraints is [canonical](#
77
79
78
80
Given two type parameters `T1` and `T2`, `T1` precedes `T2` in the canonical ordering if:
79
81
80
-
*`T1` and `T2` are generic type parameters with depths `d1` and `d2`, and indices `i1` and `i2`, respectively, and either `d1 < d2` or `d1 == d2 && i1 < i2`;
82
+
*`T1` and `T2` are generic type parameters with depths `d1` and `d2`, and indices `i1` and `i2`, respectively, and either `d1 < d2` or `d1 == d2` and `i1 < i2`;
81
83
*`T1` is a generic type parameter and `T2` is a nested type `U2.A2`; or
82
-
*`T1` is a nested type `U1.A1` and `T2` is a nested type `U2.A2`, where `A1` and `A2`name associated types of the protocols `P1` and `P2`, respectively, and either
84
+
*`T1` is a nested type `U1.A1` and `T2` is a nested type `U2.A2`, where `A1` and `A2`are associated types of the protocols `P1` and `P2`, respectively, and either
83
85
*`U1` precedes `U2` in the canonical ordering, or
84
86
*`U1 == U2` and the name of `A1` lexicographically precedes the name of `A2`, or
87
+
*`A1` is a *root* associated type (defined below) and `A2` is not a root associated type
85
88
*`U1 == U2` and `P1` precedes `P2` in the canonical ordering defined by the following section on [protocol ordering](#protocol-ordering).
86
89
90
+
A *root* associated type is an associated type that first declares that
91
+
associated type name within a protocol hierarchy. An inheriting protocol may declare an associated type with the same name, but that associated type
92
+
is not a root. For example:
93
+
94
+
```swift
95
+
protocolP {
96
+
associatedtypeA // root associated type
97
+
}
98
+
99
+
protocolQ: P {
100
+
associatedtypeB // not a root associated type ("overrides" P.A)
101
+
associatedtypeC // root associated type
102
+
}
103
+
```
104
+
87
105
### Protocol ordering
88
106
89
107
Given two protocols `P1` and `P2`, protocol `P1` precedes `P2` in the canonical ordering if:
@@ -95,16 +113,16 @@ Given two protocols `P1` and `P2`, protocol `P1` precedes `P2` in the canonical
95
113
96
114
A given constraint can be described in multiple ways. In our running example, the conformance constraint for the element type can be expressed as either `C1.Element: Equatable` or `C2.Element: Equatable`, because `C1.Element` and `C2.Element` name the same type. There might be an infinite number of ways to name the same type (e.g., `C1.SubSequence.SubSequence.Iterator.Element` is also equivalent to `C1.Element`). All of the spellings that refer to the same time comprise the *equivalence class* of that type.
97
115
98
-
Each equivalence class has a corresponding *anchor*, which is a type parameter that is the least type according to the [type parameter ordering](#type-parameter-ordering). Anchors are used to describe requirements canonically. A concrete type (i.e., a type that is not a type parameter) is canonical when each type parameters within is the anchor of its equivalence class.
116
+
Each equivalence class has a corresponding *anchor*, which is a type parameter that is the least type according to the [type parameter ordering](#type-parameter-ordering). Anchors are used to describe requirements canonically. A concrete type (i.e., a type that is not a type parameter) is canonical when each type parameter within it has either been replaced with its equivalent (canonical) concrete type (when such a constraint exists in the generic signature) or is the anchor of its equivalence class.
99
117
100
118
A layout or conformance constraint is canonical when its left-hand side is the anchor of its equivalence class. A superclass constraint is canonical when its left-hand side is the anchor of its equivalence class and its right-hand side is a canonical concrete (class) type. Same-type constraint canonicalization is discussed in detail in the following section, but some basic rules apply: the left-hand side is always a type parameter, and the right-hand side is either a type parameter that follows the left-hand side (according to the [type parameter ordering](#type-parameter-ordering)) or is a canonical concrete type.
101
119
102
120
### Same-type constaints
103
121
104
-
The canonical form of superclass, layout, and conformance constraints are trivially canonicalized using the anchor of the appropriate equivalence class. Same-type constraints, on the other hand, are responsible for forming those equivalence classes. Let's expand our running example to include a third `Collection`:
122
+
The canonical form of superclass, layout, and conformance constraints are directly canonicalizable once the equivalence classes are known. Same-type constraints, on the other hand, are responsible for forming those equivalence classes. Let's expand our running example to include a third `Collection`:
105
123
106
124
```swift
107
-
<C1, C2 where C1:Collection, C2:Collection, C3:Collection,
All of these sets of constraints have the same effect (i.e., form the same equivalence class), but the second one happens to be the canonical form.
130
148
131
-
The canonical form is determined by first dividing all of the types into distinct components. Two types `T1` and `T2` are in the same component if the same type constraint `T1 == T2` can be proven true based on other known constraints in the generic signature (i.e., if `T1 == T2` would be redundant). For example, `C1.Element` and `C1.SubSequence.Elemenent` are in the same component, because `C1: Collection` and the `Collection` protocol contains the constraint `Element == SubSequence.Element`. However, `C1.Element` and `C2.Element` are in different components.
149
+
The canonical form is determined by first dividing all of the types in the same equivalence class into distinct components. Two types `T1` and `T2` are in the same component if the same type constraint `T1 == T2` can be proven true based on other known constraints in the generic signature (i.e., if `T1 == T2` would be redundant). For example, `C1.Element` and `C1.SubSequence.Elemenent` are in the same component, because `C1: Collection` and the `Collection` protocol contains the constraint `Element == SubSequence.Element`. However, `C1.Element` and `C2.Element` are in different components.
132
150
133
151
Each component has a *local anchor*, which is a type parameter that is the least type within that component, according to the [type parameter ordering](#type-parameter-ordering). The local anchors are then sorted (again, using [type parameter ordering](#type-parameter-ordering)); call the anchors `A1`, `A2`, ..., `An` where `Ai < Aj` for `i < j`. The canonical set of constraints depends on whether the equivalence class has been constrained to a concrete type:
0 commit comments