Skip to content

Commit d4d4a70

Browse files
committed
Add documentation for how we use existentials in SwiftSyntax
1 parent ee01a3a commit d4d4a70

File tree

4 files changed

+14
-2
lines changed

4 files changed

+14
-2
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SwiftSyntaxDoccIndexTemplate.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
2727
These articles are intended for developers wishing to contribute to SwiftSyntax
2828

2929
- <doc:ChangingSwiftSyntax>
30+
- <doc:Existentials>
3031

3132
### Syntax
3233

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# When to use protocols in SwiftSyntax
2+
3+
Learn when to use protocols value types like ``ExprSyntax`` over protocols like ``ExprSyntaxProtocol``.
4+
5+
6+
SwiftSyntax tries to minimize the use of existentials (aka. protocols spelled with `any` or protocols spelled without `some`) wherever possible. This is because when the stored value is more than 3 words (a word is the size of a pointer) large, these existentials store their data on the heap. The data stored inside `RawSyntax` is bigger than 3 words and thus every time you pass a value around as a e.g. an `ExprSyntaxProtocol`, a new heap allocation will be made and that data needs to be reference-counted, which causes a very noticable performance overhead.
7+
8+
There are two more performant alternatives:
9+
- When passing a single node around, use `some ExprSyntaxProtocol`. This allows the concrete expression node (e.g. an ``IntegerLiteralExprSyntax``) to be passed directly without the need to wrap it in an existential and thus avoid the performance overhead.
10+
- When multiple expression nodes need to be represented that might be of different types, eg. in an array of expressions, use the ``ExprSyntax`` type. ``ExprSyntax`` is a struct and can thus be allocated on the stack. The downside is that specific expression nodes need to explicitly be upcast to `ExprSyntax`, eg. as `ExprSyntax(integerLiteral)`. ``ExprSyntax`` can be cast to more specific types using the `as` method, e.g. `expr.as(IntegerLiteralExprSyntax.self)`.

Sources/SwiftSyntax/Documentation.docc/SPI.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# `@_spi` attribute
22

3-
swift-syntax extensively makes extensive use of the `@_spi` attribute.
3+
Learn when SwiftSyntax exposes declaration annotated as `@_spi`.
44

5-
Functions marked as `@_spi(RawSyntax)` (where `RawSyntax` can be any name) are considered *SPI* (System Programming Interface) and are only accessible if the module that declares them is imported as `@_spi(RawSyntax)`.
5+
Functions marked as `@_spi(RawSyntax)` (where ``RawSyntax`` can be any name) are considered *SPI* (System Programming Interface) and are only accessible if the module that declares them is imported as `@_spi(RawSyntax)`.
66

77
Since functions marked as SPI are not part of the public API, swift-syntax makes no guarantee to their source stability. swift-syntax makes no effort to keep its SPI stable.
88

Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
2727
These articles are intended for developers wishing to contribute to SwiftSyntax
2828

2929
- <doc:ChangingSwiftSyntax>
30+
- <doc:Existentials>
3031

3132
### Syntax
3233

0 commit comments

Comments
 (0)