Skip to content

Commit e482078

Browse files
committed
[Syntax] Rename the as conversion functions that incur existential conversions to asProtocol
The intention is to make it clear in the API usage where existential conversion overhead exists, allowing performance critical clients to eliminate use of existentials where possible. Also add a note in README file to clarify that the API is designed with performance in mind.
1 parent 064e502 commit e482078

18 files changed

+755
-707
lines changed

Changelog.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ For increased performance, the modelling of the syntax node hierarchy has been s
8888

8989
stays the same. `ExprSyntax` is now a struct and not a protocol. See below on how to create an `ExprSyntax`.
9090

91-
**Extening a type**
91+
**Extending a type**
9292

9393
```swift
9494
// Before
@@ -118,8 +118,8 @@ For increased performance, the modelling of the syntax node hierarchy has been s
118118
```swift
119119
let identifierExprSyntax: IdentifierExprSyntax = /* ... */
120120
let node = Syntax(identifierExprSyntax)
121-
node.as(SyntaxProtocol.self) // returns a IdentifierExprSyntax with static type SyntaxProtocol
122-
node.as(ExprSyntaxProtocol.self) // returns a IdentifierExprSyntax with static type ExprSyntaxProtocol?
121+
node.asProtocol(SyntaxProtocol.self) // returns a IdentifierExprSyntax with static type SyntaxProtocol
122+
node.asProtocol(ExprSyntaxProtocol.self) // returns a IdentifierExprSyntax with static type ExprSyntaxProtocol?
123123
```
124124

125125

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ SwiftSyntax is a set of Swift bindings for the
55
allows for Swift tools to parse, inspect, generate, and transform Swift source
66
code.
77

8+
Its API is designed for performance critical applications. It uses value types almost exclusively and aims to avoid existential conversions where possible.
9+
810
> Note: SwiftSyntax is still in development, and the API is not guaranteed to
911
> be stable. It's subject to change without warning.
1012

Sources/SwiftSyntax/Misc.swift.gyb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ extension SyntaxNode {
4242
extension Syntax {
4343
/// Syntax nodes always conform to SyntaxProtocol. This API is just added
4444
/// for consistency.
45+
/// Note that this will incur an existential conversion.
4546
@available(*, deprecated, message: "Expression always evaluates to true")
46-
public func `is`(_: SyntaxProtocol.Protocol) -> Bool {
47+
public func isProtocol(_: SyntaxProtocol.Protocol) -> Bool {
4748
return true
4849
}
4950

5051
/// Return the non-type erased version of this syntax node.
51-
public func `as`(_: SyntaxProtocol.Protocol) -> SyntaxProtocol {
52+
/// Note that this will incur an existential conversion.
53+
public func asProtocol(_: SyntaxProtocol.Protocol) -> SyntaxProtocol {
5254
switch self.as(SyntaxEnum.self) {
5355
case .token(let node):
5456
return node

Sources/SwiftSyntax/Syntax.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
2626

2727
public func _validateLayout() {
2828
// Check the layout of the concrete type
29-
return self.as(SyntaxProtocol.self)._validateLayout()
29+
return self.asProtocol(SyntaxProtocol.self)._validateLayout()
3030
}
3131

3232
/// Create a `Syntax` node from a specialized syntax node.
@@ -64,7 +64,7 @@ extension Syntax: CustomReflectable {
6464
/// Reconstructs the real syntax type for this type from the node's kind and
6565
/// provides a mirror that reflects this type.
6666
public var customMirror: Mirror {
67-
return Mirror(reflecting: self.as(SyntaxProtocol.self))
67+
return Mirror(reflecting: self.asProtocol(SyntaxProtocol.self))
6868
}
6969
}
7070

Sources/SwiftSyntax/SyntaxBaseNodes.swift.gyb

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ public protocol ${node.name}Protocol: ${base_type}Protocol {}
3232
public extension Syntax {
3333
/// Check whether the non-type erased version of this syntax node conforms to
3434
/// ${node.name}Protocol.
35-
func `is`(_: ${node.name}Protocol.Protocol) -> Bool {
36-
return self.as(${node.name}Protocol.self) != nil
35+
/// Note that this will incur an existential conversion.
36+
func isProtocol(_: ${node.name}Protocol.Protocol) -> Bool {
37+
return self.asProtocol(${node.name}Protocol.self) != nil
3738
}
3839

3940
/// Return the non-type erased version of this syntax node if it conforms to
4041
/// ${node.name}Protocol. Otherwise return nil.
41-
func `as`(_: ${node.name}Protocol.Protocol) -> ${node.name}Protocol? {
42-
return self.as(SyntaxProtocol.self) as? ${node.name}Protocol
42+
/// Note that this will incur an existential conversion.
43+
func asProtocol(_: ${node.name}Protocol.Protocol) -> ${node.name}Protocol? {
44+
return self.asProtocol(SyntaxProtocol.self) as? ${node.name}Protocol
4345
}
4446
}
4547

@@ -105,22 +107,24 @@ public struct ${node.name}: ${node.name}Protocol, SyntaxHashable {
105107

106108
/// Syntax nodes always conform to `${node.name}Protocol`. This API is just
107109
/// added for consistency.
110+
/// Note that this will incur an existential conversion.
108111
@available(*, deprecated, message: "Expression always evaluates to true")
109-
public func `is`(_: ${node.name}Protocol.Protocol) -> Bool {
112+
public func isProtocol(_: ${node.name}Protocol.Protocol) -> Bool {
110113
return true
111114
}
112115

113116
/// Return the non-type erased version of this syntax node.
114-
public func `as`(_: ${node.name}Protocol.Protocol) -> ${node.name}Protocol {
115-
return Syntax(self).as(${node.name}Protocol.self)!
117+
/// Note that this will incur an existential conversion.
118+
public func asProtocol(_: ${node.name}Protocol.Protocol) -> ${node.name}Protocol {
119+
return Syntax(self).asProtocol(${node.name}Protocol.self)!
116120
}
117121
}
118122

119123
extension ${node.name}: CustomReflectable {
120124
/// Reconstructs the real syntax type for this type from the node's kind and
121125
/// provides a mirror that reflects this type.
122126
public var customMirror: Mirror {
123-
return Mirror(reflecting: Syntax(self).as(SyntaxProtocol.self))
127+
return Mirror(reflecting: Syntax(self).asProtocol(SyntaxProtocol.self))
124128
}
125129
}
126130

Sources/SwiftSyntax/SyntaxNodes.swift.gyb.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ extension ${node.name}: CustomReflectable {
189189
return Mirror(self, children: [
190190
% for child in node.children:
191191
% if child.is_optional:
192-
"${child.swift_name}": ${child.swift_name}.map(Syntax.init)?.as(SyntaxProtocol.self) as Any,
192+
"${child.swift_name}": ${child.swift_name}.map(Syntax.init)?.asProtocol(SyntaxProtocol.self) as Any,
193193
% else:
194-
"${child.swift_name}": Syntax(${child.swift_name}).as(SyntaxProtocol.self),
194+
"${child.swift_name}": Syntax(${child.swift_name}).asProtocol(SyntaxProtocol.self),
195195
% end
196196
% end
197197
])

Sources/SwiftSyntax/SyntaxTraits.swift.gyb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ public protocol ${trait.trait_name}Syntax: SyntaxProtocol {
3636
public extension SyntaxProtocol {
3737
/// Check whether the non-type erased version of this syntax node conforms to
3838
/// `${trait.trait_name}Syntax`.
39-
func `is`(_: ${trait.trait_name}Syntax.Protocol) -> Bool {
40-
return self.as(${trait.trait_name}Syntax.self) != nil
39+
/// Note that this will incur an existential conversion.
40+
func isProtocol(_: ${trait.trait_name}Syntax.Protocol) -> Bool {
41+
return self.asProtocol(${trait.trait_name}Syntax.self) != nil
4142
}
4243

4344
/// Return the non-type erased version of this syntax node if it conforms to
4445
/// `${trait.trait_name}Syntax`. Otherwise return `nil`.
45-
func `as`(_: ${trait.trait_name}Syntax.Protocol) -> ${trait.trait_name}Syntax? {
46-
return Syntax(self).as(SyntaxProtocol.self) as? ${trait.trait_name}Syntax
46+
/// Note that this will incur an existential conversion.
47+
func asProtocol(_: ${trait.trait_name}Syntax.Protocol) -> ${trait.trait_name}Syntax? {
48+
return Syntax(self).asProtocol(SyntaxProtocol.self) as? ${trait.trait_name}Syntax
4749
}
4850
}
4951

Sources/SwiftSyntax/gyb_generated/Misc.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,13 +1393,15 @@ extension SyntaxNode {
13931393
extension Syntax {
13941394
/// Syntax nodes always conform to SyntaxProtocol. This API is just added
13951395
/// for consistency.
1396+
/// Note that this will incur an existential conversion.
13961397
@available(*, deprecated, message: "Expression always evaluates to true")
1397-
public func `is`(_: SyntaxProtocol.Protocol) -> Bool {
1398+
public func isProtocol(_: SyntaxProtocol.Protocol) -> Bool {
13981399
return true
13991400
}
14001401

14011402
/// Return the non-type erased version of this syntax node.
1402-
public func `as`(_: SyntaxProtocol.Protocol) -> SyntaxProtocol {
1403+
/// Note that this will incur an existential conversion.
1404+
public func asProtocol(_: SyntaxProtocol.Protocol) -> SyntaxProtocol {
14031405
switch self.as(SyntaxEnum.self) {
14041406
case .token(let node):
14051407
return node

0 commit comments

Comments
 (0)