Skip to content

Commit 685768d

Browse files
committed
Re-model type specifiers and allow multiple specifiers on a type
The previous design of having a single specifier on an `AttributedTypeSyntax` no longer sufficied because a function paramter type can have multiple specifiers, such as `borrowing _const String`. Re-design the way type specifiers are represented by introducing type nodes for every specifier kind: `ConstTypeSyntax` for `_const`, `IsolatedTypeSyntax` for `isolated`, `LifetimeDependenceParameterSyntax` for `_copy(parameterName)` etc., `LifetimeDependenceTypeSyntax` for `inout`, `__shared` etc., and `ResultDependsOnTypeSyntax` for `_resultDependsOn`. rdar://118125715
1 parent 92dbcbc commit 685768d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3032
-412
lines changed

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

+15-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ public enum Keyword: CaseIterable {
8787
case _Class
8888
case _compilerInitialized
8989
case _const
90+
case _consume
9091
case _consuming
92+
case _copy
9193
case _documentation
9294
case _dynamicReplacement
9395
case _effects
@@ -98,6 +100,7 @@ public enum Keyword: CaseIterable {
98100
case _local
99101
case _modify
100102
case _move
103+
case _mutate
101104
case _mutating
102105
case _NativeClass
103106
case _NativeRefCountedObject
@@ -307,6 +310,8 @@ public enum Keyword: CaseIterable {
307310
return KeywordSpec("_backDeploy")
308311
case ._borrow:
309312
return KeywordSpec("_borrow")
313+
case ._borrowing:
314+
return KeywordSpec("_borrowing", experimentalFeature: .referenceBindings)
310315
case ._BridgeObject:
311316
return KeywordSpec("_BridgeObject")
312317
case ._cdecl:
@@ -317,6 +322,12 @@ public enum Keyword: CaseIterable {
317322
return KeywordSpec("_compilerInitialized")
318323
case ._const:
319324
return KeywordSpec("_const")
325+
case ._consume:
326+
return KeywordSpec("_consume", experimentalFeature: .nonescapableTypes)
327+
case ._consuming:
328+
return KeywordSpec("_consuming", experimentalFeature: .referenceBindings)
329+
case ._copy:
330+
return KeywordSpec("_copy", experimentalFeature: .nonescapableTypes)
320331
case ._documentation:
321332
return KeywordSpec("_documentation")
322333
case ._dynamicReplacement:
@@ -337,6 +348,10 @@ public enum Keyword: CaseIterable {
337348
return KeywordSpec("_modify")
338349
case ._move:
339350
return KeywordSpec("_move")
351+
case ._mutating:
352+
return KeywordSpec("_mutating", experimentalFeature: .referenceBindings)
353+
case ._mutate:
354+
return KeywordSpec("_mutate", experimentalFeature: .nonescapableTypes)
340355
case ._NativeClass:
341356
return KeywordSpec("_NativeClass")
342357
case ._NativeRefCountedObject:
@@ -722,12 +737,6 @@ public enum Keyword: CaseIterable {
722737
return KeywordSpec("wrt")
723738
case .yield:
724739
return KeywordSpec("yield")
725-
case ._borrowing:
726-
return KeywordSpec("_borrowing", experimentalFeature: .referenceBindings)
727-
case ._consuming:
728-
return KeywordSpec("_consuming", experimentalFeature: .referenceBindings)
729-
case ._mutating:
730-
return KeywordSpec("_mutating", experimentalFeature: .referenceBindings)
731740
}
732741
}
733742
}

CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift

+12-5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public enum SyntaxNodeKind: String, CaseIterable {
7575
case conditionElement
7676
case conditionElementList
7777
case conformanceRequirement
78+
case constType
7879
case consumeExpr
7980
case continueStmt
8081
case conventionAttributeArguments
@@ -99,8 +100,8 @@ public enum SyntaxNodeKind: String, CaseIterable {
99100
case dictionaryExpr
100101
case dictionaryType
101102
case differentiabilityArgument
102-
case differentiabilityArguments
103103
case differentiabilityArgumentList
104+
case differentiabilityArguments
104105
case differentiabilityWithRespectToArgument
105106
case differentiableAttributeArguments
106107
case discardAssignmentExpr
@@ -170,6 +171,7 @@ public enum SyntaxNodeKind: String, CaseIterable {
170171
case inOutExpr
171172
case integerLiteralExpr
172173
case isExpr
174+
case isolatedType
173175
case isTypePattern
174176
case keyPathComponent
175177
case keyPathComponentList
@@ -182,6 +184,10 @@ public enum SyntaxNodeKind: String, CaseIterable {
182184
case labeledSpecializeArgument
183185
case labeledStmt
184186
case layoutRequirement
187+
case lifetimeDependenceParameter
188+
case lifetimeDependenceParameterList
189+
case lifetimeDependenceType
190+
case lifetimeSpecifiedType
185191
case macroDecl
186192
case macroExpansionDecl
187193
case macroExpansionExpr
@@ -240,18 +246,19 @@ public enum SyntaxNodeKind: String, CaseIterable {
240246
case protocolDecl
241247
case regexLiteralExpr
242248
case repeatStmt
249+
case resultDependsOnType
243250
case returnClause
244251
case returnStmt
245252
case sameTypeRequirement
246253
case sequenceExpr
254+
case simpleStringLiteralExpr
255+
case simpleStringLiteralSegmentList
247256
case someOrAnyType
248257
case sourceFile
249258
case specializeAttributeArgumentList
250259
case specializeAvailabilityArgument
251260
case specializeTargetFunctionArgument
252261
case stmt
253-
case simpleStringLiteralExpr
254-
case simpleStringLiteralSegmentList
255262
case stringLiteralExpr
256263
case stringLiteralSegmentList
257264
case stringSegment
@@ -299,10 +306,10 @@ public enum SyntaxNodeKind: String, CaseIterable {
299306
case whereClause
300307
case whileStmt
301308
case wildcardPattern
302-
case yieldStmt
303309
case yieldedExpression
304-
case yieldedExpressionsClause
305310
case yieldedExpressionList
311+
case yieldedExpressionsClause
312+
case yieldStmt
306313

307314
// Nodes that have special handling throughout the codebase
308315

CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift

+130-15
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,6 @@ public let TYPE_NODES: [Node] = [
4242
"WithAttributes"
4343
],
4444
children: [
45-
Child(
46-
name: "specifier",
47-
kind: .token(choices: [
48-
.keyword(.inout),
49-
.keyword(.__shared),
50-
.keyword(.__owned),
51-
.keyword(.isolated),
52-
.keyword(._const),
53-
.keyword(.borrowing),
54-
.keyword(.consuming),
55-
.keyword(.transferring),
56-
.keyword(._resultDependsOn),
57-
]),
58-
isOptional: true
59-
),
6045
Child(
6146
name: "attributes",
6247
kind: .collection(kind: .attributeList, collectionElementName: "Attribute", defaultsToEmpty: true)
@@ -116,6 +101,22 @@ public let TYPE_NODES: [Node] = [
116101
]
117102
),
118103

104+
Node(
105+
kind: .constType,
106+
base: .type,
107+
nameForDiagnostics: nil,
108+
documentation: """
109+
TODO: What does _const mean?
110+
""",
111+
children: [
112+
Child(
113+
name: "constKeyword",
114+
kind: .token(choices: [.keyword(._const)])
115+
),
116+
Child(name: "baseType", kind: .node(kind: .type)),
117+
]
118+
),
119+
119120
Node(
120121
kind: .someOrAnyType,
121122
base: .type,
@@ -267,6 +268,103 @@ public let TYPE_NODES: [Node] = [
267268
]
268269
),
269270

271+
Node(
272+
kind: .isolatedType,
273+
base: .type,
274+
nameForDiagnostics: nil,
275+
documentation: """
276+
The type of a function parameter that specifies that the paramter is isolated to (TODO what is the paramter isolated to?)
277+
""",
278+
children: [
279+
Child(
280+
name: "isolatedKeyword",
281+
kind: .token(choices: [.keyword(.isolated)])
282+
),
283+
Child(name: "baseType", kind: .node(kind: .type)),
284+
]
285+
),
286+
287+
Node(
288+
kind: .lifetimeDependenceType,
289+
base: .type,
290+
experimentalFeature: .nonescapableTypes,
291+
nameForDiagnostics: nil,
292+
documentation: """
293+
A function return type that specifies which parameters its lifetime depends on (TODO: Is this even correct?)
294+
""",
295+
children: [
296+
Child(
297+
name: "lifetimeDependenceSpecifier",
298+
kind: .token(choices: [.keyword(._copy), .keyword(._consume), .keyword(._borrow), .keyword(._mutate)])
299+
),
300+
Child(
301+
name: "leftParen",
302+
kind: .token(choices: [.token(.leftParen)])
303+
),
304+
Child(
305+
name: "parameters",
306+
deprecatedName: "arguments",
307+
kind: .collection(kind: .lifetimeDependenceParameterList, collectionElementName: "Parameter")
308+
),
309+
Child(
310+
name: "rightParen",
311+
kind: .token(choices: [.token(.rightParen)])
312+
),
313+
Child(name: "baseType", kind: .node(kind: .type)),
314+
]
315+
),
316+
317+
// TODO: Should these be called parameters or arguments?
318+
Node(
319+
kind: .lifetimeDependenceParameter,
320+
base: .syntax,
321+
experimentalFeature: .nonescapableTypes,
322+
nameForDiagnostics: nil,
323+
documentation: """
324+
A parameter to a lifetime dependence annotation to a type.
325+
326+
### Examples
327+
- `x` in `_mutate(x)`
328+
- `1` in `_borrow(1)` TODO: What does this even mean?
329+
- `self` in `_consume(self)`
330+
""",
331+
traits: [
332+
"WithTrailingComma"
333+
],
334+
children: [
335+
Child(name: "parameter", kind: .token(choices: [.token(.identifier), .token(.integerLiteral), .keyword(.`self`)])),
336+
Child(
337+
name: "trailingComma",
338+
kind: .token(choices: [.token(.comma)]),
339+
isOptional: true
340+
),
341+
]
342+
),
343+
344+
Node(
345+
kind: .lifetimeDependenceParameterList,
346+
base: .syntaxCollection,
347+
experimentalFeature: .nonescapableTypes,
348+
nameForDiagnostics: nil,
349+
elementChoices: [.lifetimeDependenceParameter]
350+
),
351+
352+
Node(
353+
kind: .lifetimeSpecifiedType,
354+
base: .type,
355+
nameForDiagnostics: nil,
356+
documentation: """
357+
The type of a function parameter that explicitly specifies the lifetime transfer as `borrowing`, `transferring`, or `consuming`.
358+
""",
359+
children: [
360+
Child(
361+
name: "lifetimeSpecifier",
362+
kind: .token(choices: [.keyword(.__shared), .keyword(.__owned), .keyword(.borrowing), .keyword(.transferring), .keyword(.consuming), .keyword(.inout)])
363+
),
364+
Child(name: "baseType", kind: .node(kind: .type)),
365+
]
366+
),
367+
270368
Node(
271369
kind: .memberType,
272370
base: .type,
@@ -424,6 +522,23 @@ public let TYPE_NODES: [Node] = [
424522
]
425523
),
426524

525+
Node(
526+
kind: .resultDependsOnType,
527+
base: .type,
528+
experimentalFeature: .nonescapableTypes,
529+
nameForDiagnostics: nil,
530+
documentation: """
531+
TODO: What does _resultDependsOn mean?
532+
""",
533+
children: [
534+
Child(
535+
name: "resultDependsOnKeyword",
536+
kind: .token(choices: [.keyword(._resultDependsOn)])
537+
),
538+
Child(name: "baseType", kind: .node(kind: .type)),
539+
]
540+
),
541+
427542
Node(
428543
kind: .tupleTypeElementList,
429544
base: .syntaxCollection,

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/ResultBuildersFile.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Utils
1818
let resultBuildersFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
1919
DeclSyntax("import SwiftSyntax")
2020

21-
for node in SYNTAX_NODES.compactMap(\.collectionNode) {
21+
for node in SYNTAX_NODES.compactMap(\.collectionNode) where node.experimentalFeature == nil {
2222
let type = SyntaxBuildableType(kind: .node(kind: node.kind))
2323

2424
try! StructDeclSyntax(

CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift

+7-6
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class ValidateSyntaxNodes: XCTestCase {
166166
}
167167
switch choice {
168168
case .keyword(let keyword):
169-
let keywordName = keyword.spec.name
169+
let keywordName = keyword.spec.name.dropPrefix("_")
170170

171171
if child.isFollowedByColonToken(in: node) {
172172
if child.varOrCaseName.description != "\(keywordName)Label" {
@@ -289,11 +289,6 @@ class ValidateSyntaxNodes: XCTestCase {
289289
),
290290

291291
// MARK: Tokens that contain underscores
292-
ValidationFailure(
293-
node: .borrowExpr,
294-
message: "child 'borrowKeyword' has a single keyword as its only token choice and should thus be named '_borrowKeyword'"
295-
// _borrow is underscored and thus BorrowKeyword is the correct spelling
296-
),
297292
ValidationFailure(
298293
node: .conventionWitnessMethodAttributeArguments,
299294
message:
@@ -507,6 +502,7 @@ class ValidateSyntaxNodes: XCTestCase {
507502
ValidationFailure(node: .editorPlaceholderExpr, message: "could conform to trait 'MissingNode' but does not"),
508503
ValidationFailure(node: .enumCaseElement, message: "could conform to trait 'NamedDecl' but does not"),
509504
ValidationFailure(node: .genericParameter, message: "could conform to trait 'NamedDecl' but does not"),
505+
ValidationFailure(node: .lifetimeDependenceType, message: "could conform to trait 'Parenthesized' but does not"),
510506
ValidationFailure(node: .precedenceGroupName, message: "could conform to trait 'NamedDecl' but does not"),
511507
ValidationFailure(node: .primaryAssociatedType, message: "could conform to trait 'NamedDecl' but does not"),
512508
ValidationFailure(node: .yieldedExpressionsClause, message: "could conform to trait 'Parenthesized' but does not"),
@@ -664,12 +660,17 @@ class ValidateSyntaxNodes: XCTestCase {
664660
ValidationFailure(node: .attributedType, message: "child 'baseType' should not end with 'Type'"),
665661
ValidationFailure(node: .conformanceRequirement, message: "child 'leftType' should not end with 'Type'"),
666662
ValidationFailure(node: .conformanceRequirement, message: "child 'rightType' should not end with 'Type'"),
663+
ValidationFailure(node: .constType, message: "child 'baseType' should not end with 'Type'"),
667664
ValidationFailure(node: .extensionDecl, message: "child 'extendedType' should not end with 'Type'"),
668665
ValidationFailure(node: .genericParameter, message: "child 'inheritedType' should not end with 'Type'"),
669666
ValidationFailure(node: .implicitlyUnwrappedOptionalType, message: "child 'wrappedType' should not end with 'Type'"),
667+
ValidationFailure(node: .isolatedType, message: "child 'baseType' should not end with 'Type'"),
668+
ValidationFailure(node: .lifetimeDependenceType, message: "child 'baseType' should not end with 'Type'"),
669+
ValidationFailure(node: .lifetimeSpecifiedType, message: "child 'baseType' should not end with 'Type'"),
670670
ValidationFailure(node: .memberType, message: "child 'baseType' should not end with 'Type'"),
671671
ValidationFailure(node: .metatypeType, message: "child 'baseType' should not end with 'Type'"),
672672
ValidationFailure(node: .optionalType, message: "child 'wrappedType' should not end with 'Type'"),
673+
ValidationFailure(node: .resultDependsOnType, message: "child 'baseType' should not end with 'Type'"),
673674
ValidationFailure(node: .sameTypeRequirement, message: "child 'leftType' should not end with 'Type'"),
674675
ValidationFailure(node: .sameTypeRequirement, message: "child 'rightType' should not end with 'Type'"),
675676
// MARK: Adjective + Expr

Release Notes/511.md

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
- `EditorPlaceholderDeclSyntax` and `EditorPlaceholderExprSyntax`:
6161
- Description: `EditorPlaceholderDeclSyntax` and `EditorPlaceholderExprSyntax` are now deprecated and placeholders are instead parsed as identifiers within a `MissingDeclSyntax` or `DeclReferenceExprSyntax`.
6262
- Pull request: https://github.com/apple/swift-syntax/pull/2237
63+
64+
- Type parameter modelling was changed
65+
- Description: The previous design of having a single specifier on an `AttributedTypeSyntax` no longer sufficied because a function paramter type can have multiple specifiers, such as `borrowing _const String`. Re-design the way type specifiers are represented by introducing type nodes for every specifier kind: `ConstTypeSyntax` for `_const`, `IsolatedTypeSyntax` for `isolated`, `LifetimeDependenceParameterSyntax` for `_copy(parameterName)` etc., `LifetimeDependenceTypeSyntax` for `inout`, `__shared` etc., and `ResultDependsOnTypeSyntax` for `_resultDependsOn`.
66+
- Pull request: https://github.com/apple/swift-syntax/pull/2433
6367

6468
## API-Incompatible Changes
6569

Sources/SwiftParser/Parameters.swift

+2-5
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,10 @@ extension Parser {
259259
}
260260

261261
mutating func parseMisplacedSpecifiers() -> [RawTokenSyntax] {
262-
var misplacedSpecifiers: [RawTokenSyntax] = []
263262
if self.withLookahead({ !$0.startsParameterName(isClosure: false, allowMisplacedSpecifierRecovery: false) }) {
264-
while canHaveParameterSpecifier, let specifier = self.consume(ifAnyIn: TypeSpecifier.self) {
265-
misplacedSpecifiers.append(specifier)
266-
}
263+
return consumeMisplacedParameterSpecifiers()
267264
}
268-
return misplacedSpecifiers
265+
return []
269266
}
270267
}
271268

0 commit comments

Comments
 (0)