Skip to content

Commit 6645096

Browse files
authored
Merge pull request #1669 from gottesmm/rdar101862423
[copy-operator] Add parsing support for copy operator.
2 parents 0711d21 + b3d38fd commit 6645096

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
@@ -1192,7 +1192,7 @@ public let EXPR_NODES: [Node] = [
11921192
// The move expr
11931193
Node(
11941194
name: "MoveExpr",
1195-
nameForDiagnostics: "'_move' expression",
1195+
nameForDiagnostics: "'consume' expression",
11961196
kind: "Expr",
11971197
children: [
11981198
Child(
@@ -1206,6 +1206,22 @@ public let EXPR_NODES: [Node] = [
12061206
]
12071207
),
12081208

1209+
Node(
1210+
name: "CopyExpr",
1211+
nameForDiagnostics: "'copy' expression",
1212+
kind: "Expr",
1213+
children: [
1214+
Child(
1215+
name: "CopyKeyword",
1216+
kind: .token(choices: [.keyword(text: "copy")])
1217+
),
1218+
Child(
1219+
name: "Expression",
1220+
kind: .node(kind: "Expr")
1221+
),
1222+
]
1223+
),
1224+
12091225
Node(
12101226
name: "MultipleTrailingClosureElementList",
12111227
nameForDiagnostics: nil,

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public let KEYWORDS: [KeywordSpec] = [
110110
KeywordSpec("class", isLexerClassified: true, requiresTrailingSpace: true),
111111
KeywordSpec("compiler"),
112112
KeywordSpec("consume"),
113+
KeywordSpec("copy"),
113114
KeywordSpec("consuming"),
114115
KeywordSpec("continue", isLexerClassified: true, requiresTrailingSpace: true),
115116
KeywordSpec("convenience"),

Sources/SwiftParser/Expressions.swift

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

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

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

488518
let consumeTok = self.eat(handle)
@@ -499,8 +529,9 @@ extension Parser {
499529
)
500530
)
501531
case nil:
502-
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
532+
break
503533
}
534+
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
504535
}
505536

506537
/// 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
@@ -478,12 +478,13 @@ public enum TypeSpecifier: TokenSpecSet {
478478

479479
// MARK: Expression start
480480

481-
enum AwaitTryMove: TokenSpecSet {
481+
enum ExpressionModifierKeyword: TokenSpecSet {
482482
case awaitKeyword
483483
case _moveKeyword
484484
case _borrowKeyword
485485
case tryKeyword
486486
case consumeKeyword
487+
case copyKeyword
487488

488489
init?(lexeme: Lexer.Lexeme) {
489490
switch PrepareForKeywordMatch(lexeme) {
@@ -492,6 +493,7 @@ enum AwaitTryMove: TokenSpecSet {
492493
case TokenSpec(._borrow): self = ._borrowKeyword
493494
case TokenSpec(.try): self = .tryKeyword
494495
case TokenSpec(.consume): self = .consumeKeyword
496+
case TokenSpec(.copy): self = .copyKeyword
495497
default: return nil
496498
}
497499
}
@@ -502,6 +504,7 @@ enum AwaitTryMove: TokenSpecSet {
502504
case ._moveKeyword: return .keyword(._move)
503505
case ._borrowKeyword: return .keyword(._borrow)
504506
case .consumeKeyword: return .keyword(.consume)
507+
case .copyKeyword: return .keyword(.copy)
505508
case .tryKeyword: return .keyword(.try)
506509
}
507510
}
@@ -697,13 +700,13 @@ enum PrimaryExpressionStart: TokenSpecSet {
697700
/// - `MatchingPatternStart`
698701
/// - `PrimaryExpressionStart`
699702
enum ExpressionStart: TokenSpecSet {
700-
case awaitTryMove(AwaitTryMove)
703+
case awaitTryMove(ExpressionModifierKeyword)
701704
case expressionPrefixOperator(ExpressionPrefixOperator)
702705
case primaryExpressionStart(PrimaryExpressionStart)
703706
case ifOrSwitch(IfOrSwitch)
704707

705708
init?(lexeme: Lexer.Lexeme) {
706-
if let subset = AwaitTryMove(lexeme: lexeme) {
709+
if let subset = ExpressionModifierKeyword(lexeme: lexeme) {
707710
self = .awaitTryMove(subset)
708711
} else if let subset = ExpressionPrefixOperator(lexeme: lexeme) {
709712
self = .expressionPrefixOperator(subset)
@@ -717,7 +720,7 @@ enum ExpressionStart: TokenSpecSet {
717720
}
718721

719722
static var allCases: [ExpressionStart] {
720-
return AwaitTryMove.allCases.map(Self.awaitTryMove)
723+
return ExpressionModifierKeyword.allCases.map(Self.awaitTryMove)
721724
+ ExpressionPrefixOperator.allCases.map(Self.expressionPrefixOperator)
722725
+ PrimaryExpressionStart.allCases.map(Self.primaryExpressionStart)
723726
+ IfOrSwitch.allCases.map(Self.ifOrSwitch)

Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ extension SyntaxKind {
109109
return "@convention(...) arguments"
110110
case .conventionWitnessMethodAttributeArguments:
111111
return "@convention(...) arguments for witness methods"
112+
case .copyExpr:
113+
return "'copy' expression"
112114
case .declModifier:
113115
return "modifier"
114116
case .declName:
@@ -272,7 +274,7 @@ extension SyntaxKind {
272274
case .missingType:
273275
return "type"
274276
case .moveExpr:
275-
return "'_move' expression"
277+
return "'consume' expression"
276278
case .multipleTrailingClosureElement:
277279
return "trailing closure"
278280
case .namedOpaqueReturnType:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
9696
- <doc:SwiftSyntax/CanImportExprSyntax>
9797
- <doc:SwiftSyntax/CanImportVersionInfoSyntax>
9898
- <doc:SwiftSyntax/ClosureExprSyntax>
99+
- <doc:SwiftSyntax/CopyExprSyntax>
99100
- <doc:SwiftSyntax/DictionaryExprSyntax>
100101
- <doc:SwiftSyntax/DiscardAssignmentExprSyntax>
101102
- <doc:SwiftSyntax/EditorPlaceholderExprSyntax>

Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
787787
return "protocolName"
788788
case \ConventionWitnessMethodAttributeArgumentsSyntax.unexpectedAfterProtocolName:
789789
return "unexpectedAfterProtocolName"
790+
case \CopyExprSyntax.unexpectedBeforeCopyKeyword:
791+
return "unexpectedBeforeCopyKeyword"
792+
case \CopyExprSyntax.copyKeyword:
793+
return "copyKeyword"
794+
case \CopyExprSyntax.unexpectedBetweenCopyKeywordAndExpression:
795+
return "unexpectedBetweenCopyKeywordAndExpression"
796+
case \CopyExprSyntax.expression:
797+
return "expression"
798+
case \CopyExprSyntax.unexpectedAfterExpression:
799+
return "unexpectedAfterExpression"
790800
case \DeclModifierDetailSyntax.unexpectedBeforeLeftParen:
791801
return "unexpectedBeforeLeftParen"
792802
case \DeclModifierDetailSyntax.leftParen:

Sources/SwiftSyntax/generated/Keyword.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public enum Keyword: UInt8, Hashable {
8686
case `class`
8787
case compiler
8888
case consume
89+
case copy
8990
case consuming
9091
case `continue`
9192
case convenience
@@ -268,6 +269,8 @@ public enum Keyword: UInt8, Hashable {
268269
self = ._spi
269270
case "case":
270271
self = .`case`
272+
case "copy":
273+
self = .copy
271274
case "each":
272275
self = .each
273276
case "else":
@@ -826,6 +829,7 @@ public enum Keyword: UInt8, Hashable {
826829
"class",
827830
"compiler",
828831
"consume",
832+
"copy",
829833
"consuming",
830834
"continue",
831835
"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?(_ node: some SyntaxProtocol) {
208208
switch node.raw.kind {
209-
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .canImportExpr, .canImportVersionInfo, .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, .canImportExpr, .canImportVersionInfo, .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, .canImportExpr, .canImportVersionInfo, .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, .canImportExpr, .canImportVersionInfo, .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)")
@@ -265,6 +265,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
265265
.node(CanImportExprSyntax.self),
266266
.node(CanImportVersionInfoSyntax.self),
267267
.node(ClosureExprSyntax.self),
268+
.node(CopyExprSyntax.self),
268269
.node(DictionaryExprSyntax.self),
269270
.node(DiscardAssignmentExprSyntax.self),
270271
.node(EditorPlaceholderExprSyntax.self),
@@ -751,6 +752,7 @@ extension Syntax {
751752
.node(ContinueStmtSyntax.self),
752753
.node(ConventionAttributeArgumentsSyntax.self),
753754
.node(ConventionWitnessMethodAttributeArgumentsSyntax.self),
755+
.node(CopyExprSyntax.self),
754756
.node(DeclModifierDetailSyntax.self),
755757
.node(DeclModifierSyntax.self),
756758
.node(DeclNameArgumentListSyntax.self),

Sources/SwiftSyntax/generated/SyntaxEnum.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public enum SyntaxEnum {
8080
case continueStmt(ContinueStmtSyntax)
8181
case conventionAttributeArguments(ConventionAttributeArgumentsSyntax)
8282
case conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax)
83+
case copyExpr(CopyExprSyntax)
8384
case declModifierDetail(DeclModifierDetailSyntax)
8485
case declModifier(DeclModifierSyntax)
8586
case declNameArgumentList(DeclNameArgumentListSyntax)
@@ -426,6 +427,8 @@ public extension Syntax {
426427
return .conventionAttributeArguments(ConventionAttributeArgumentsSyntax(self)!)
427428
case .conventionWitnessMethodAttributeArguments:
428429
return .conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax(self)!)
430+
case .copyExpr:
431+
return .copyExpr(CopyExprSyntax(self)!)
429432
case .declModifierDetail:
430433
return .declModifierDetail(DeclModifierDetailSyntax(self)!)
431434
case .declModifier:

Sources/SwiftSyntax/generated/SyntaxKind.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public enum SyntaxKind {
8080
case continueStmt
8181
case conventionAttributeArguments
8282
case conventionWitnessMethodAttributeArguments
83+
case copyExpr
8384
case declModifierDetail
8485
case declModifier
8586
case declNameArgumentList
@@ -543,6 +544,8 @@ public enum SyntaxKind {
543544
return ConventionAttributeArgumentsSyntax.self
544545
case .conventionWitnessMethodAttributeArguments:
545546
return ConventionWitnessMethodAttributeArgumentsSyntax.self
547+
case .copyExpr:
548+
return CopyExprSyntax.self
546549
case .declModifierDetail:
547550
return DeclModifierDetailSyntax.self
548551
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
@@ -2920,6 +2927,20 @@ open class SyntaxRewriter {
29202927
return Syntax(visit(node))
29212928
}
29222929

2930+
/// Implementation detail of visit(_:). Do not call directly.
2931+
private func visitImplCopyExprSyntax(_ data: SyntaxData) -> Syntax {
2932+
let node = CopyExprSyntax(data)
2933+
// Accessing _syntaxNode directly is faster than calling Syntax(node)
2934+
visitPre(node._syntaxNode)
2935+
defer {
2936+
visitPost(node._syntaxNode)
2937+
}
2938+
if let newNode = visitAny(node._syntaxNode) {
2939+
return newNode
2940+
}
2941+
return Syntax(visit(node))
2942+
}
2943+
29232944
/// Implementation detail of visit(_:). Do not call directly.
29242945
private func visitImplDeclModifierDetailSyntax(_ data: SyntaxData) -> Syntax {
29252946
let node = DeclModifierDetailSyntax(data)
@@ -6004,6 +6025,8 @@ open class SyntaxRewriter {
60046025
return visitImplConventionAttributeArgumentsSyntax
60056026
case .conventionWitnessMethodAttributeArguments:
60066027
return visitImplConventionWitnessMethodAttributeArgumentsSyntax
6028+
case .copyExpr:
6029+
return visitImplCopyExprSyntax
60076030
case .declModifierDetail:
60086031
return visitImplDeclModifierDetailSyntax
60096032
case .declModifier:
@@ -6560,6 +6583,8 @@ open class SyntaxRewriter {
65606583
return visitImplConventionAttributeArgumentsSyntax(data)
65616584
case .conventionWitnessMethodAttributeArguments:
65626585
return visitImplConventionWitnessMethodAttributeArgumentsSyntax(data)
6586+
case .copyExpr:
6587+
return visitImplCopyExprSyntax(data)
65636588
case .declModifierDetail:
65646589
return visitImplDeclModifierDetailSyntax(data)
65656590
case .declModifier:

0 commit comments

Comments
 (0)