Skip to content

Commit b2eefce

Browse files
authored
Merge pull request #1982 from gottesmm/reference-binding
[reference-binding] Add _consuming/_mutating/_borrowing as var decl bindings
2 parents 1060677 + 73d271d commit b2eefce

20 files changed

+517
-183
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2330,7 +2330,10 @@ public let DECL_NODES: [Node] = [
23302330
Child(
23312331
name: "bindingSpecifier",
23322332
deprecatedName: "bindingKeyword",
2333-
kind: .token(choices: [.keyword(.let), .keyword(.var), .keyword(.inout)]),
2333+
kind: .token(choices: [
2334+
.keyword(.let), .keyword(.var), .keyword(.inout),
2335+
.keyword(._mutating), .keyword(._borrowing), .keyword(._consuming),
2336+
]),
23342337
documentation: """
23352338
The specifier that defines the type of the variables declared (`let` or `var`).
23362339
"""

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,12 @@ public enum Keyword: CaseIterable {
6767
case _alignment
6868
case _backDeploy
6969
case _borrow
70+
case _borrowing
7071
case _cdecl
7172
case _Class
7273
case _compilerInitialized
7374
case _const
75+
case _consuming
7476
case _documentation
7577
case _dynamicReplacement
7678
case _effects
@@ -81,6 +83,7 @@ public enum Keyword: CaseIterable {
8183
case _local
8284
case _modify
8385
case _move
86+
case _mutating
8487
case _NativeClass
8588
case _NativeRefCountedObject
8689
case _noMetadata
@@ -675,6 +678,12 @@ public enum Keyword: CaseIterable {
675678
return KeywordSpec("wrt")
676679
case .yield:
677680
return KeywordSpec("yield")
681+
case ._borrowing:
682+
return KeywordSpec("_borrowing", isExperimental: true)
683+
case ._consuming:
684+
return KeywordSpec("_consuming", isExperimental: true)
685+
case ._mutating:
686+
return KeywordSpec("_mutating", isExperimental: true)
678687
}
679688
}
680689
}

CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ public let PATTERN_NODES: [Node] = [
140140
// value-binding-pattern -> 'let' pattern
141141
// | 'var' pattern
142142
// | 'inout' pattern
143+
// | '_mutating' pattern
144+
// | '_consuming' pattern
145+
// | '_borrowing' pattern
143146
Node(
144147
kind: .valueBindingPattern,
145148
base: .pattern,
@@ -148,7 +151,10 @@ public let PATTERN_NODES: [Node] = [
148151
Child(
149152
name: "bindingSpecifier",
150153
deprecatedName: "bindingKeyword",
151-
kind: .token(choices: [.keyword(.let), .keyword(.var), .keyword(.inout)])
154+
kind: .token(choices: [
155+
.keyword(.let), .keyword(.var), .keyword(.inout),
156+
.keyword(._mutating), .keyword(._borrowing), .keyword(._consuming),
157+
])
152158
),
153159
Child(
154160
name: "pattern",

CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,10 @@ public let STMT_NODES: [Node] = [
435435
Child(
436436
name: "bindingSpecifier",
437437
deprecatedName: "bindingKeyword",
438-
kind: .token(choices: [.keyword(.let), .keyword(.var), .keyword(.inout)])
438+
kind: .token(choices: [
439+
.keyword(.let), .keyword(.var), .keyword(.inout), .keyword(._mutating), .keyword(._borrowing),
440+
.keyword(._consuming),
441+
])
439442
),
440443
Child(
441444
name: "pattern",

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserTokenSpecSetFile.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import SyntaxSupport
1616
import Utils
1717

1818
let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
19-
DeclSyntax("@_spi(RawSyntax) import SwiftSyntax")
19+
DeclSyntax("@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax")
2020

2121
for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode) {
2222
for child in layoutNode.children {
@@ -31,7 +31,12 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
3131
for choice in choices {
3232
switch choice {
3333
case .keyword(let keyword):
34-
DeclSyntax("case \(raw: keyword.spec.escapedName)")
34+
DeclSyntax(
35+
"""
36+
\(keyword.spec.apiAttributes)\
37+
case \(raw: keyword.spec.escapedName)
38+
"""
39+
)
3540
case .token(let token):
3641
DeclSyntax("case \(token.spec.varOrCaseName)")
3742
}

Sources/SwiftParser/Declarations.swift

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extension TokenConsumer {
106106
declStartKeyword = subparser.at(anyIn: DeclarationKeyword.self)?.0
107107
}
108108
switch declStartKeyword {
109-
case .actor:
109+
case .lhs(.actor):
110110
// actor Foo {}
111111
if subparser.peek().rawTokenKind == .identifier {
112112
return true
@@ -119,16 +119,16 @@ extension TokenConsumer {
119119
lookahead.consumeAnyToken()
120120
} while lookahead.atStartOfDeclaration(isAtTopLevel: isAtTopLevel, allowInitDecl: allowInitDecl)
121121
return lookahead.at(.identifier)
122-
case .case:
122+
case .lhs(.case):
123123
// When 'case' appears inside a function, it's probably a switch
124124
// case, not an enum case declaration.
125125
return false
126-
case .`init`:
126+
case .lhs(.`init`):
127127
return allowInitDecl
128-
case .macro:
128+
case .lhs(.macro):
129129
// macro Foo ...
130130
return subparser.peek().rawTokenKind == .identifier
131-
case .pound:
131+
case .lhs(.pound):
132132
// Force parsing '#<identifier>' after attributes as a macro expansion decl.
133133
if hasAttribute || hasModifier {
134134
return true
@@ -210,81 +210,99 @@ extension Parser {
210210
// while recovering to the declaration start.
211211
let recoveryPrecedence = inMemberDeclList ? TokenPrecedence.closingBrace : nil
212212

213-
switch self.canRecoverTo(anyIn: DeclarationKeyword.self, overrideRecoveryPrecedence: recoveryPrecedence) {
214-
case (.import, let handle)?:
213+
CanRecoverToSwitch: switch self.canRecoverTo(anyIn: DeclarationKeyword.self, overrideRecoveryPrecedence: recoveryPrecedence) {
214+
case (.lhs(.import), let handle)?:
215215
return RawDeclSyntax(self.parseImportDeclaration(attrs, handle))
216-
case (.class, let handle)?:
216+
case (.lhs(.class), let handle)?:
217217
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawClassDeclSyntax.self, attrs: attrs, introucerHandle: handle))
218-
case (.enum, let handle)?:
218+
case (.lhs(.enum), let handle)?:
219219
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawEnumDeclSyntax.self, attrs: attrs, introucerHandle: handle))
220-
case (.case, let handle)?:
220+
case (.lhs(.case), let handle)?:
221221
return RawDeclSyntax(self.parseEnumCaseDeclaration(attrs, handle))
222-
case (.struct, let handle)?:
222+
case (.lhs(.struct), let handle)?:
223223
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawStructDeclSyntax.self, attrs: attrs, introucerHandle: handle))
224-
case (.protocol, let handle)?:
224+
case (.lhs(.protocol), let handle)?:
225225
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawProtocolDeclSyntax.self, attrs: attrs, introucerHandle: handle))
226-
case (.associatedtype, let handle)?:
226+
case (.lhs(.associatedtype), let handle)?:
227227
return RawDeclSyntax(self.parseAssociatedTypeDeclaration(attrs, handle))
228-
case (.typealias, let handle)?:
228+
case (.lhs(.typealias), let handle)?:
229229
return RawDeclSyntax(self.parseTypealiasDeclaration(attrs, handle))
230-
case (.extension, let handle)?:
230+
case (.lhs(.extension), let handle)?:
231231
return RawDeclSyntax(self.parseExtensionDeclaration(attrs, handle))
232-
case (.func, let handle)?:
232+
case (.lhs(.func), let handle)?:
233233
return RawDeclSyntax(self.parseFuncDeclaration(attrs, handle))
234-
case (.subscript, let handle)?:
234+
case (.lhs(.subscript), let handle)?:
235235
return RawDeclSyntax(self.parseSubscriptDeclaration(attrs, handle))
236-
case (.let, let handle)?, (.var, let handle)?,
237-
(.inout, let handle)?:
238-
return RawDeclSyntax(self.parseBindingDeclaration(attrs, handle, inMemberDeclList: inMemberDeclList))
239-
case (.`init`, let handle)?:
236+
case (.lhs(.`init`), let handle)?:
240237
return RawDeclSyntax(self.parseInitializerDeclaration(attrs, handle))
241-
case (.deinit, let handle)?:
238+
case (.lhs(.deinit), let handle)?:
242239
return RawDeclSyntax(self.parseDeinitializerDeclaration(attrs, handle))
243-
case (.operator, let handle)?:
240+
case (.lhs(.operator), let handle)?:
244241
return RawDeclSyntax(self.parseOperatorDeclaration(attrs, handle))
245-
case (.precedencegroup, let handle)?:
242+
case (.lhs(.precedencegroup), let handle)?:
246243
return RawDeclSyntax(self.parsePrecedenceGroupDeclaration(attrs, handle))
247-
case (.actor, let handle)?:
244+
case (.lhs(.actor), let handle)?:
248245
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawActorDeclSyntax.self, attrs: attrs, introucerHandle: handle))
249-
case (.macro, let handle)?:
246+
case (.lhs(.macro), let handle)?:
250247
return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle))
251-
case (.pound, let handle)?:
248+
case (.lhs(.pound), let handle)?:
252249
return RawDeclSyntax(self.parseMacroExpansionDeclaration(attrs, handle))
250+
case (.rhs(let binding), let handle)?:
251+
switch binding {
252+
case ._mutating:
253+
fallthrough
254+
case ._borrowing:
255+
fallthrough
256+
case ._consuming:
257+
guard experimentalFeatures.contains(.referenceBindings) else {
258+
break CanRecoverToSwitch
259+
}
260+
fallthrough
261+
case .let:
262+
fallthrough
263+
case .var:
264+
fallthrough
265+
case .inout:
266+
// Handle all cases of `ValueBindingPatternSyntax.BindingSpecifierOptions` in the same way.
267+
return RawDeclSyntax(self.parseBindingDeclaration(attrs, handle, inMemberDeclList: inMemberDeclList))
268+
}
253269
case nil:
254-
if inMemberDeclList {
255-
let isProbablyVarDecl = self.at(.identifier, .wildcard) && self.peek(isAt: .colon, .equal, .comma)
256-
let isProbablyTupleDecl = self.at(.leftParen) && self.peek(isAt: .identifier, .wildcard)
270+
break
271+
}
257272

258-
if isProbablyVarDecl || isProbablyTupleDecl {
259-
return RawDeclSyntax(self.parseBindingDeclaration(attrs, .missing(.keyword(.var))))
260-
}
273+
if inMemberDeclList {
274+
let isProbablyVarDecl = self.at(.identifier, .wildcard) && self.peek(isAt: .colon, .equal, .comma)
275+
let isProbablyTupleDecl = self.at(.leftParen) && self.peek(isAt: .identifier, .wildcard)
261276

262-
if self.currentToken.isEditorPlaceholder {
263-
let placeholder = self.consumeAnyToken()
264-
return RawDeclSyntax(
265-
RawEditorPlaceholderDeclSyntax(
266-
attributes: attrs.attributes,
267-
modifiers: attrs.modifiers,
268-
placeholder: placeholder,
269-
arena: self.arena
270-
)
277+
if isProbablyVarDecl || isProbablyTupleDecl {
278+
return RawDeclSyntax(self.parseBindingDeclaration(attrs, .missing(.keyword(.var))))
279+
}
280+
281+
if self.currentToken.isEditorPlaceholder {
282+
let placeholder = self.consumeAnyToken()
283+
return RawDeclSyntax(
284+
RawEditorPlaceholderDeclSyntax(
285+
attributes: attrs.attributes,
286+
modifiers: attrs.modifiers,
287+
placeholder: placeholder,
288+
arena: self.arena
271289
)
272-
}
290+
)
291+
}
273292

274-
let isProbablyFuncDecl = self.at(.identifier, .wildcard) || self.at(anyIn: Operator.self) != nil
293+
let isProbablyFuncDecl = self.at(.identifier, .wildcard) || self.at(anyIn: Operator.self) != nil
275294

276-
if isProbablyFuncDecl {
277-
return RawDeclSyntax(self.parseFuncDeclaration(attrs, .missing(.keyword(.func))))
278-
}
295+
if isProbablyFuncDecl {
296+
return RawDeclSyntax(self.parseFuncDeclaration(attrs, .missing(.keyword(.func))))
279297
}
280-
return RawDeclSyntax(
281-
RawMissingDeclSyntax(
282-
attributes: attrs.attributes,
283-
modifiers: attrs.modifiers,
284-
arena: self.arena
285-
)
286-
)
287298
}
299+
return RawDeclSyntax(
300+
RawMissingDeclSyntax(
301+
attributes: attrs.attributes,
302+
modifiers: attrs.modifiers,
303+
arena: self.arena
304+
)
305+
)
288306
}
289307
}
290308

Sources/SwiftParser/ExperimentalFeatures.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,8 @@ extension Parser {
1717
public init(rawValue: UInt) {
1818
self.rawValue = rawValue
1919
}
20+
21+
/// Whether to enable the parsing of 'reference bindings'.
22+
public static let referenceBindings = Self(rawValue: 1 << 0)
2023
}
2124
}

0 commit comments

Comments
 (0)