Skip to content

Commit ab3ce4a

Browse files
authored
Merge pull request #1680 from gottesmm/release-5.9-copy-consume
[5.9] Add support for the copy operator and fix parsing issues around consume
2 parents d367cf0 + 0ed0759 commit ab3ce4a

File tree

20 files changed

+593
-21
lines changed

20 files changed

+593
-21
lines changed

CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ public let EXPR_NODES: [Node] = [
11261126
// The move expr
11271127
Node(
11281128
name: "MoveExpr",
1129-
nameForDiagnostics: "'_move' expression",
1129+
nameForDiagnostics: "'consume' expression",
11301130
kind: "Expr",
11311131
children: [
11321132
Child(
@@ -1140,6 +1140,22 @@ public let EXPR_NODES: [Node] = [
11401140
]
11411141
),
11421142

1143+
Node(
1144+
name: "CopyExpr",
1145+
nameForDiagnostics: "'copy' expression",
1146+
kind: "Expr",
1147+
children: [
1148+
Child(
1149+
name: "CopyKeyword",
1150+
kind: .token(choices: [.keyword(text: "copy")])
1151+
),
1152+
Child(
1153+
name: "Expression",
1154+
kind: .node(kind: "Expr")
1155+
),
1156+
]
1157+
),
1158+
11431159
Node(
11441160
name: "MultipleTrailingClosureElementList",
11451161
nameForDiagnostics: nil,

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public let KEYWORDS: [KeywordSpec] = [
106106
KeywordSpec("catch", isLexerClassified: true, requiresLeadingSpace: true),
107107
KeywordSpec("class", isLexerClassified: true, requiresTrailingSpace: true),
108108
KeywordSpec("consume"),
109+
KeywordSpec("copy"),
109110
KeywordSpec("consuming"),
110111
KeywordSpec("continue", isLexerClassified: true, requiresTrailingSpace: true),
111112
KeywordSpec("convenience"),

Sources/SwiftParser/Expressions.swift

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ extension Parser {
411411
}
412412
}
413413

414-
switch self.at(anyIn: AwaitTryMove.self) {
414+
EXPR_PREFIX: switch self.at(anyIn: ExpressionModifierKeyword.self) {
415415
case (.awaitKeyword, let handle)?:
416416
let awaitTok = self.eat(handle)
417417
let sub = self.parseSequenceExpressionElement(
@@ -472,18 +472,48 @@ extension Parser {
472472
)
473473
)
474474

475+
case (.copyKeyword, let handle)?:
476+
// `copy` is only contextually a keyword, if it's followed by an
477+
// identifier or keyword on the same line. We do this to ensure that we do
478+
// not break any copy functions defined by users. This is following with
479+
// what we have done for the consume keyword.
480+
switch self.peek() {
481+
case TokenSpec(.identifier, allowAtStartOfLine: false),
482+
TokenSpec(.dollarIdentifier, allowAtStartOfLine: false),
483+
TokenSpec(.self, allowAtStartOfLine: false):
484+
break
485+
default:
486+
// Break out of `outer switch` on failure.
487+
break EXPR_PREFIX
488+
}
489+
490+
let copyTok = self.eat(handle)
491+
let sub = self.parseSequenceExpressionElement(
492+
flavor,
493+
forDirective: forDirective,
494+
pattern: pattern
495+
)
496+
return RawExprSyntax(
497+
RawCopyExprSyntax(
498+
copyKeyword: copyTok,
499+
expression: sub,
500+
arena: self.arena
501+
)
502+
)
503+
475504
case (.consumeKeyword, let handle)?:
476505
// `consume` is only contextually a keyword, if it's followed by an
477-
// identifier or keyword on the same line.
478-
let next = peek()
479-
if next.isAtStartOfLine {
480-
fallthrough
481-
}
482-
if next.rawTokenKind != .identifier,
483-
next.rawTokenKind != .dollarIdentifier,
484-
next.rawTokenKind != .keyword
485-
{
486-
fallthrough
506+
// identifier or keyword on the same line. We do this to ensure that we do
507+
// not break any copy functions defined by users. This is following with
508+
// what we have done for the consume keyword.
509+
switch self.peek() {
510+
case TokenSpec(.identifier, allowAtStartOfLine: false),
511+
TokenSpec(.dollarIdentifier, allowAtStartOfLine: false),
512+
TokenSpec(.self, allowAtStartOfLine: false):
513+
break
514+
default:
515+
// Break out of the outer `switch`.
516+
break EXPR_PREFIX
487517
}
488518

489519
let consumeTok = self.eat(handle)
@@ -500,8 +530,9 @@ extension Parser {
500530
)
501531
)
502532
case nil:
503-
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
533+
break
504534
}
535+
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
505536
}
506537

507538
/// Parse an optional prefix operator followed by an expression.

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,12 +452,13 @@ public enum TypeSpecifier: TokenSpecSet {
452452

453453
// MARK: Expression start
454454

455-
enum AwaitTryMove: TokenSpecSet {
455+
enum ExpressionModifierKeyword: TokenSpecSet {
456456
case awaitKeyword
457457
case _moveKeyword
458458
case _borrowKeyword
459459
case tryKeyword
460460
case consumeKeyword
461+
case copyKeyword
461462

462463
init?(lexeme: Lexer.Lexeme) {
463464
switch PrepareForKeywordMatch(lexeme) {
@@ -466,6 +467,7 @@ enum AwaitTryMove: TokenSpecSet {
466467
case TokenSpec(._borrow): self = ._borrowKeyword
467468
case TokenSpec(.try): self = .tryKeyword
468469
case TokenSpec(.consume): self = .consumeKeyword
470+
case TokenSpec(.copy): self = .copyKeyword
469471
default: return nil
470472
}
471473
}
@@ -476,6 +478,7 @@ enum AwaitTryMove: TokenSpecSet {
476478
case ._moveKeyword: return .keyword(._move)
477479
case ._borrowKeyword: return .keyword(._borrow)
478480
case .consumeKeyword: return .keyword(.consume)
481+
case .copyKeyword: return .keyword(.copy)
479482
case .tryKeyword: return .keyword(.try)
480483
}
481484
}
@@ -668,13 +671,13 @@ enum PrimaryExpressionStart: TokenSpecSet {
668671
/// - `MatchingPatternStart`
669672
/// - `PrimaryExpressionStart`
670673
enum ExpressionStart: TokenSpecSet {
671-
case awaitTryMove(AwaitTryMove)
674+
case awaitTryMove(ExpressionModifierKeyword)
672675
case expressionPrefixOperator(ExpressionPrefixOperator)
673676
case primaryExpressionStart(PrimaryExpressionStart)
674677
case ifOrSwitch(IfOrSwitch)
675678

676679
init?(lexeme: Lexer.Lexeme) {
677-
if let subset = AwaitTryMove(lexeme: lexeme) {
680+
if let subset = ExpressionModifierKeyword(lexeme: lexeme) {
678681
self = .awaitTryMove(subset)
679682
} else if let subset = ExpressionPrefixOperator(lexeme: lexeme) {
680683
self = .expressionPrefixOperator(subset)
@@ -688,7 +691,7 @@ enum ExpressionStart: TokenSpecSet {
688691
}
689692

690693
static var allCases: [ExpressionStart] {
691-
return AwaitTryMove.allCases.map(Self.awaitTryMove)
694+
return ExpressionModifierKeyword.allCases.map(Self.awaitTryMove)
692695
+ ExpressionPrefixOperator.allCases.map(Self.expressionPrefixOperator)
693696
+ PrimaryExpressionStart.allCases.map(Self.primaryExpressionStart)
694697
+ IfOrSwitch.allCases.map(Self.ifOrSwitch)

Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ extension SyntaxKind {
107107
return "@convention(...) arguments"
108108
case .conventionWitnessMethodAttributeArguments:
109109
return "@convention(...) arguments for witness methods"
110+
case .copyExpr:
111+
return "'copy' expression"
110112
case .declModifier:
111113
return "modifier"
112114
case .declName:
@@ -270,7 +272,7 @@ extension SyntaxKind {
270272
case .missingType:
271273
return "type"
272274
case .moveExpr:
273-
return "'_move' expression"
275+
return "'consume' expression"
274276
case .multipleTrailingClosureElement:
275277
return "trailing closure"
276278
case .namedOpaqueReturnType:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
9494
- <doc:SwiftSyntax/BooleanLiteralExprSyntax>
9595
- <doc:SwiftSyntax/BorrowExprSyntax>
9696
- <doc:SwiftSyntax/ClosureExprSyntax>
97+
- <doc:SwiftSyntax/CopyExprSyntax>
9798
- <doc:SwiftSyntax/DictionaryExprSyntax>
9899
- <doc:SwiftSyntax/DiscardAssignmentExprSyntax>
99100
- <doc:SwiftSyntax/EditorPlaceholderExprSyntax>

Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
757757
return "protocolName"
758758
case \ConventionWitnessMethodAttributeArgumentsSyntax.unexpectedAfterProtocolName:
759759
return "unexpectedAfterProtocolName"
760+
case \CopyExprSyntax.unexpectedBeforeCopyKeyword:
761+
return "unexpectedBeforeCopyKeyword"
762+
case \CopyExprSyntax.copyKeyword:
763+
return "copyKeyword"
764+
case \CopyExprSyntax.unexpectedBetweenCopyKeywordAndExpression:
765+
return "unexpectedBetweenCopyKeywordAndExpression"
766+
case \CopyExprSyntax.expression:
767+
return "expression"
768+
case \CopyExprSyntax.unexpectedAfterExpression:
769+
return "unexpectedAfterExpression"
760770
case \DeclModifierDetailSyntax.unexpectedBeforeLeftParen:
761771
return "unexpectedBeforeLeftParen"
762772
case \DeclModifierDetailSyntax.leftParen:

Sources/SwiftSyntax/generated/Keyword.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public enum Keyword: UInt8, Hashable {
8383
case `catch`
8484
case `class`
8585
case consume
86+
case copy
8687
case consuming
8788
case `continue`
8889
case convenience
@@ -265,6 +266,8 @@ public enum Keyword: UInt8, Hashable {
265266
self = ._spi
266267
case "case":
267268
self = .`case`
269+
case "copy":
270+
self = .copy
268271
case "each":
269272
self = .each
270273
case "else":
@@ -806,6 +809,7 @@ public enum Keyword: UInt8, Hashable {
806809
"catch",
807810
"class",
808811
"consume",
812+
"copy",
809813
"consuming",
810814
"continue",
811815
"convenience",

Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor {
573573
visitAnyPost(node._syntaxNode)
574574
}
575575

576+
override open func visit(_ node: CopyExprSyntax) -> SyntaxVisitorContinueKind {
577+
return visitAny(node._syntaxNode)
578+
}
579+
580+
override open func visitPost(_ node: CopyExprSyntax) {
581+
visitAnyPost(node._syntaxNode)
582+
}
583+
576584
override open func visit(_ node: DeclModifierDetailSyntax) -> SyntaxVisitorContinueKind {
577585
return visitAny(node._syntaxNode)
578586
}

Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
206206

207207
public init?<S: SyntaxProtocol>(_ node: S) {
208208
switch node.raw.kind {
209-
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .closureExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
209+
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .closureExpr, .copyExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
210210
self._syntaxNode = node._syntaxNode
211211
default:
212212
return nil
@@ -218,7 +218,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
218218
/// is undefined.
219219
internal init(_ data: SyntaxData) {
220220
switch data.raw.kind {
221-
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .closureExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
221+
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .closureExpr, .copyExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
222222
break
223223
default:
224224
preconditionFailure("Unable to create ExprSyntax from \(data.raw.kind)")
@@ -263,6 +263,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
263263
.node(BooleanLiteralExprSyntax.self),
264264
.node(BorrowExprSyntax.self),
265265
.node(ClosureExprSyntax.self),
266+
.node(CopyExprSyntax.self),
266267
.node(DictionaryExprSyntax.self),
267268
.node(DiscardAssignmentExprSyntax.self),
268269
.node(EditorPlaceholderExprSyntax.self),
@@ -749,6 +750,7 @@ extension Syntax {
749750
.node(ContinueStmtSyntax.self),
750751
.node(ConventionAttributeArgumentsSyntax.self),
751752
.node(ConventionWitnessMethodAttributeArgumentsSyntax.self),
753+
.node(CopyExprSyntax.self),
752754
.node(DeclModifierDetailSyntax.self),
753755
.node(DeclModifierSyntax.self),
754756
.node(DeclNameArgumentListSyntax.self),

Sources/SwiftSyntax/generated/SyntaxEnum.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public enum SyntaxEnum {
8181
case continueStmt(ContinueStmtSyntax)
8282
case conventionAttributeArguments(ConventionAttributeArgumentsSyntax)
8383
case conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax)
84+
case copyExpr(CopyExprSyntax)
8485
case declModifierDetail(DeclModifierDetailSyntax)
8586
case declModifier(DeclModifierSyntax)
8687
case declNameArgumentList(DeclNameArgumentListSyntax)
@@ -423,6 +424,8 @@ public extension Syntax {
423424
return .conventionAttributeArguments(ConventionAttributeArgumentsSyntax(self)!)
424425
case .conventionWitnessMethodAttributeArguments:
425426
return .conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax(self)!)
427+
case .copyExpr:
428+
return .copyExpr(CopyExprSyntax(self)!)
426429
case .declModifierDetail:
427430
return .declModifierDetail(DeclModifierDetailSyntax(self)!)
428431
case .declModifier:

Sources/SwiftSyntax/generated/SyntaxKind.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public enum SyntaxKind {
8181
case continueStmt
8282
case conventionAttributeArguments
8383
case conventionWitnessMethodAttributeArguments
84+
case copyExpr
8485
case declModifierDetail
8586
case declModifier
8687
case declNameArgumentList
@@ -538,6 +539,8 @@ public enum SyntaxKind {
538539
return ConventionAttributeArgumentsSyntax.self
539540
case .conventionWitnessMethodAttributeArguments:
540541
return ConventionWitnessMethodAttributeArgumentsSyntax.self
542+
case .copyExpr:
543+
return CopyExprSyntax.self
541544
case .declModifierDetail:
542545
return DeclModifierDetailSyntax.self
543546
case .declModifier:

Sources/SwiftSyntax/generated/SyntaxRewriter.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,13 @@ open class SyntaxRewriter {
480480
return Syntax(visitChildren(node)).cast(ConventionWitnessMethodAttributeArgumentsSyntax.self)
481481
}
482482

483+
/// Visit a `CopyExprSyntax`.
484+
/// - Parameter node: the node that is being visited
485+
/// - Returns: the rewritten node
486+
open func visit(_ node: CopyExprSyntax) -> ExprSyntax {
487+
return ExprSyntax(visitChildren(node))
488+
}
489+
483490
/// Visit a `DeclModifierDetailSyntax`.
484491
/// - Parameter node: the node that is being visited
485492
/// - Returns: the rewritten node
@@ -2892,6 +2899,20 @@ open class SyntaxRewriter {
28922899
return Syntax(visit(node))
28932900
}
28942901

2902+
/// Implementation detail of visit(_:). Do not call directly.
2903+
private func visitImplCopyExprSyntax(_ data: SyntaxData) -> Syntax {
2904+
let node = CopyExprSyntax(data)
2905+
// Accessing _syntaxNode directly is faster than calling Syntax(node)
2906+
visitPre(node._syntaxNode)
2907+
defer {
2908+
visitPost(node._syntaxNode)
2909+
}
2910+
if let newNode = visitAny(node._syntaxNode) {
2911+
return newNode
2912+
}
2913+
return Syntax(visit(node))
2914+
}
2915+
28952916
/// Implementation detail of visit(_:). Do not call directly.
28962917
private func visitImplDeclModifierDetailSyntax(_ data: SyntaxData) -> Syntax {
28972918
let node = DeclModifierDetailSyntax(data)
@@ -5920,6 +5941,8 @@ open class SyntaxRewriter {
59205941
return visitImplConventionAttributeArgumentsSyntax
59215942
case .conventionWitnessMethodAttributeArguments:
59225943
return visitImplConventionWitnessMethodAttributeArgumentsSyntax
5944+
case .copyExpr:
5945+
return visitImplCopyExprSyntax
59235946
case .declModifierDetail:
59245947
return visitImplDeclModifierDetailSyntax
59255948
case .declModifier:
@@ -6468,6 +6491,8 @@ open class SyntaxRewriter {
64686491
return visitImplConventionAttributeArgumentsSyntax(data)
64696492
case .conventionWitnessMethodAttributeArguments:
64706493
return visitImplConventionWitnessMethodAttributeArgumentsSyntax(data)
6494+
case .copyExpr:
6495+
return visitImplCopyExprSyntax(data)
64716496
case .declModifierDetail:
64726497
return visitImplDeclModifierDetailSyntax(data)
64736498
case .declModifier:

0 commit comments

Comments
 (0)