Skip to content

Commit 440ca7d

Browse files
authored
Merge pull request #80114 from eeckstein/document-types
docs: add a section about formal vs lowered types in the SIL documentation
2 parents 6f09b80 + 96e7e30 commit 440ca7d

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

docs/SIL/SIL.md

+50
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,56 @@ largely according to Swift's type grammar.
108108
sil-type ::= '$' '*'? generic-parameter-list? type
109109
```
110110

111+
## Formal vs. Lowered Types
112+
113+
A formal type corresponds to a Swift type as it is defined in the source code.
114+
The AST and the type checker work with formal types. Formal types can be
115+
canonicalized which resolves type aliases and removes sugar. Later stages of
116+
the compiler, like the SIL optimizer, only deal with canonical formal types.
117+
Therefore, if we speak about formal types in the following sections, we always
118+
refer to _canonical_ formal types.
119+
120+
Each formal type has a corresponding lowered type. However, most lowered types
121+
are identical to their original formal type, for example all nominal types,
122+
like classes, structs or enums (except `Optional`). Only a few kind of types
123+
are lowered to a different lowered type. The most prominent example is function
124+
types: a lowered function type adds information about the calling convention and
125+
it lowers tuple arguments to individual arguments.
126+
127+
For example, the formal type of
128+
129+
```
130+
func foo(a: (Int, String), b: any P) { }
131+
```
132+
133+
is `((Int, String), any P) -> ()` whereas its lowered type is
134+
`(Int, @guaranteed String, @in_guaranteed any P) -> ()`.
135+
136+
Deriving a lowered type from a formal type is called _type lowering_ which is
137+
described in detail in the [Types](Types.md#Type-Lowering) document.
138+
139+
SIL types are always lowered types. The soundness of the SIL type system
140+
depends on lowered types and the SIL optimizer needs lowered types to perform
141+
correct optimizations.
142+
143+
However, there are a few places where SIL needs to refer to formal types. These
144+
are operations on types which are "user visible", for example cast
145+
instructions.
146+
147+
For example, a cast from `((Int, Bool)) -> ()` to `(Int, Bool) -> ()` fails
148+
because the two formal function types differ. If a SIL cast instruction would
149+
operate on SIL types, the cast would incorrectly succeed because the formal
150+
types of those functions types are equivalent.
151+
152+
To summarize:
153+
154+
| | Definition | Example |
155+
| ------------------ | -------------------------------------------- | ----------------------------------- |
156+
| **Formal type** | original type from the source code | `typealias C = ((Int, Bool)) -> ()` |
157+
| **Canonical type** | formal type minus sugar, aliases resolved | `((Int, Bool)) -> ()` |
158+
| **SIL type** | lowered canonical type, plus is-address flag | `$*(Int, Bool) -> ()` |
159+
160+
111161
## Loadable vs. Address-only Types
112162

113163
Most SIL types are _loadable_. That means that a value of such a type can be

0 commit comments

Comments
 (0)