Skip to content

Commit 54d61bc

Browse files
committed
docs: add a section about formal vs lowered types in the SIL documentation
1 parent 1f16262 commit 54d61bc

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

docs/SIL/SIL.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,57 @@ 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. Only a few kind of types are lowered to a
123+
different lowered type. The most prominent example is function types: a lowered
124+
function type adds information about the calling convention and it lowers tuple
125+
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_. For
137+
detailed information about type lowering see the
138+
[Types](Types.md#Type-Lowering) document.
139+
140+
SIL types are always lowered types. The soundness of the SIL type system
141+
depends on lowered types and the SIL optimizer needs lowered types to perform
142+
correct optimizations.
143+
144+
However, there are a few places where SIL needs to refer to formal types. These
145+
are operations on types which are "user visible", for example cast
146+
instructions.
147+
148+
For example, a cast from `((Int, Bool)) -> ()` to `(Int, Bool) -> ()` fails
149+
because the two formal function types differ. If a SIL cast instruction would
150+
operate on SIL types, the cast would incorrectly succeed because the formal
151+
types of those functions types are equivalent.
152+
153+
To summarize:
154+
155+
| | Definition | Example |
156+
| ------------------ | --------------------------------------------- | ----------------------------------- |
157+
| **Formal type** | original type from the source code | `typealias C = ((Int, Bool)) -> ()` |
158+
| **Canonical type** | formal type minus sugar, aliases resolved | `((Int, Bool)) -> ()` |
159+
| **SIL type** | lowered canonical type, plus is-address flag | `$*(Int, Bool) -> ()` |
160+
161+
111162
## Loadable vs. Address-only Types
112163

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

0 commit comments

Comments
 (0)