Skip to content

Commit d70578d

Browse files
authored
Merge pull request #2574 from apple/cpdependson
[6.0] Update lifetime dependence syntax
2 parents 3e91e97 + d216b0c commit d70578d

20 files changed

+241
-552
lines changed

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ public enum Keyword: CaseIterable {
108108
case _Class
109109
case _compilerInitialized
110110
case _const
111-
case _consume
112111
case _consuming
113-
case _copy
114112
case _documentation
115113
case _dynamicReplacement
116114
case _effects
@@ -121,7 +119,6 @@ public enum Keyword: CaseIterable {
121119
case _local
122120
case _modify
123121
case _move
124-
case _mutate
125122
case _mutating
126123
case _NativeClass
127124
case _NativeRefCountedObject
@@ -186,6 +183,7 @@ public enum Keyword: CaseIterable {
186183
case `default`
187184
case `defer`
188185
case `deinit`
186+
case dependsOn
189187
case deprecated
190188
case derivative
191189
case didSet
@@ -275,6 +273,7 @@ public enum Keyword: CaseIterable {
275273
case reverse
276274
case right
277275
case safe
276+
case scoped
278277
case `self`
279278
case `Self`
280279
case Sendable
@@ -343,12 +342,8 @@ public enum Keyword: CaseIterable {
343342
return KeywordSpec("_compilerInitialized")
344343
case ._const:
345344
return KeywordSpec("_const")
346-
case ._consume:
347-
return KeywordSpec("_consume", experimentalFeature: .nonescapableTypes)
348345
case ._consuming:
349346
return KeywordSpec("_consuming", experimentalFeature: .referenceBindings)
350-
case ._copy:
351-
return KeywordSpec("_copy", experimentalFeature: .nonescapableTypes)
352347
case ._documentation:
353348
return KeywordSpec("_documentation")
354349
case ._dynamicReplacement:
@@ -369,8 +364,6 @@ public enum Keyword: CaseIterable {
369364
return KeywordSpec("_modify")
370365
case ._move:
371366
return KeywordSpec("_move")
372-
case ._mutate:
373-
return KeywordSpec("_mutate", experimentalFeature: .nonescapableTypes)
374367
case ._mutating:
375368
return KeywordSpec("_mutating", experimentalFeature: .referenceBindings)
376369
case ._NativeClass:
@@ -499,6 +492,8 @@ public enum Keyword: CaseIterable {
499492
return KeywordSpec("defer", isLexerClassified: true)
500493
case .deinit:
501494
return KeywordSpec("deinit", isLexerClassified: true)
495+
case .dependsOn:
496+
return KeywordSpec("dependsOn", experimentalFeature: .nonescapableTypes)
502497
case .deprecated:
503498
return KeywordSpec("deprecated")
504499
case .derivative:
@@ -675,6 +670,8 @@ public enum Keyword: CaseIterable {
675670
return KeywordSpec("right")
676671
case .safe:
677672
return KeywordSpec("safe")
673+
case .scoped:
674+
return KeywordSpec("scoped", experimentalFeature: .nonescapableTypes)
678675
case .self:
679676
return KeywordSpec("self", isLexerClassified: true)
680677
case .Self:

CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -543,30 +543,30 @@ public let TYPE_NODES: [Node] = [
543543
),
544544

545545
Node(
546-
kind: .lifetimeSpecifierArguments,
546+
kind: .lifetimeTypeSpecifier,
547547
base: .syntax,
548548
experimentalFeature: .nonescapableTypes,
549-
nameForDiagnostics: nil,
550-
documentation: """
551-
An optional argument passed to a type parameter.
552-
553-
### Example
554-
`borrow(data)` in `func foo(data: Array<Item>) -> borrow(data) ComplexReferenceType`
555-
""",
556-
traits: [
557-
"Parenthesized"
558-
],
549+
nameForDiagnostics: "lifetime specifier",
550+
documentation: "A specifier that specifies function parameter on whose lifetime a type depends",
559551
children: [
552+
Child(
553+
name: "dependsOnKeyword",
554+
kind: .token(choices: [.keyword(.dependsOn)]),
555+
documentation: "lifetime dependence specifier on the return type"
556+
),
560557
Child(
561558
name: "leftParen",
562559
kind: .token(choices: [.token(.leftParen)])
563560
),
561+
Child(
562+
name: "scopedKeyword",
563+
kind: .token(choices: [.keyword(.scoped)]),
564+
documentation: "lifetime of return value is scoped to the lifetime of the original value",
565+
isOptional: true
566+
),
564567
Child(
565568
name: "arguments",
566-
kind: .collection(kind: .lifetimeSpecifierArgumentList, collectionElementName: "Arguments"),
567-
documentation: """
568-
The function parameters that the lifetime of the annotated type depends on.
569-
"""
569+
kind: .collection(kind: .lifetimeSpecifierArgumentList, collectionElementName: "Arguments")
570570
),
571571
Child(
572572
name: "rightParen",
@@ -575,30 +575,6 @@ public let TYPE_NODES: [Node] = [
575575
]
576576
),
577577

578-
Node(
579-
kind: .lifetimeTypeSpecifier,
580-
base: .syntax,
581-
experimentalFeature: .nonescapableTypes,
582-
nameForDiagnostics: "lifetime specifier",
583-
documentation: "A specifier that specifies function parameter on whose lifetime a type depends",
584-
children: [
585-
Child(
586-
name: "specifier",
587-
kind: .token(choices: [
588-
.keyword(._copy),
589-
.keyword(._consume),
590-
.keyword(._borrow),
591-
.keyword(._mutate),
592-
]),
593-
documentation: "The specifier token that's attached to the type."
594-
),
595-
Child(
596-
name: "arguments",
597-
kind: .node(kind: .lifetimeSpecifierArguments)
598-
),
599-
]
600-
),
601-
602578
Node(
603579
kind: .simpleTypeSpecifier,
604580
base: .syntax,

CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ class ValidateSyntaxNodes: XCTestCase {
550550
node: .yieldedExpressionsClause,
551551
message: "could conform to trait 'Parenthesized' but does not"
552552
),
553+
ValidationFailure(node: .lifetimeTypeSpecifier, message: "could conform to trait 'Parenthesized' but does not"),
553554
]
554555
)
555556
}

Sources/SwiftParser/TokenPrecedence.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ enum TokenPrecedence: Comparable {
233233
.__setter_access, .indirect, .isolated, .nonisolated, .distributed, ._local,
234234
.inout, ._mutating, ._borrow, ._borrowing, .borrowing, ._consuming, .consuming, .consume, ._resultDependsOnSelf,
235235
._resultDependsOn,
236-
.transferring, ._consume, ._copy, ._mutate,
236+
.transferring, .dependsOn, .scoped,
237237
// Accessors
238238
.get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress,
239239
.mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, ._modify,

Sources/SwiftParser/Types.swift

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -900,33 +900,31 @@ extension Parser.Lookahead {
900900
}
901901

902902
extension Parser {
903-
private mutating func parseLifetimeTypeSpecifier(
904-
specifierHandle: TokenConsumptionHandle
905-
) -> RawTypeSpecifierListSyntax.Element {
906-
let specifier = self.eat(specifierHandle)
903+
private mutating func parseLifetimeTypeSpecifier() -> RawTypeSpecifierListSyntax.Element {
904+
let (unexpectedBeforeDependsOnKeyword, dependsOnKeyword) = self.expect(.keyword(.dependsOn))
907905

908906
guard let leftParen = self.consume(if: .leftParen) else {
909907
// If there is no left paren, add an entirely missing detail. Otherwise, we start to consume the following type
910908
// name as a token inside the detail, which leads to confusing recovery results.
911-
let arguments = RawLifetimeSpecifierArgumentsSyntax(
912-
leftParen: missingToken(.leftParen),
913-
arguments: RawLifetimeSpecifierArgumentListSyntax(
914-
elements: [
915-
RawLifetimeSpecifierArgumentSyntax(parameter: missingToken(.identifier), trailingComma: nil, arena: arena)
916-
],
917-
arena: self.arena
918-
),
919-
rightParen: missingToken(.rightParen),
909+
let lifetimeSpecifierArgumentList = RawLifetimeSpecifierArgumentListSyntax(
910+
elements: [
911+
RawLifetimeSpecifierArgumentSyntax(parameter: missingToken(.identifier), trailingComma: nil, arena: arena)
912+
],
920913
arena: self.arena
921914
)
922915
let lifetimeSpecifier = RawLifetimeTypeSpecifierSyntax(
923-
specifier: specifier,
924-
arguments: arguments,
916+
unexpectedBeforeDependsOnKeyword,
917+
dependsOnKeyword: dependsOnKeyword,
918+
leftParen: missingToken(.leftParen),
919+
scopedKeyword: nil,
920+
arguments: lifetimeSpecifierArgumentList,
921+
rightParen: missingToken(.rightParen),
925922
arena: self.arena
926923
)
927924
return .lifetimeTypeSpecifier(lifetimeSpecifier)
928925
}
929926

927+
let scoped = self.consume(if: .keyword(.scoped))
930928
var keepGoing: RawTokenSyntax?
931929
var arguments: [RawLifetimeSpecifierArgumentSyntax] = []
932930
var loopProgress = LoopProgressCondition()
@@ -947,18 +945,16 @@ extension Parser {
947945
} while keepGoing != nil && self.hasProgressed(&loopProgress)
948946
let lifetimeSpecifierArgumentList = RawLifetimeSpecifierArgumentListSyntax(elements: arguments, arena: self.arena)
949947
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
950-
let argumentsSyntax = RawLifetimeSpecifierArgumentsSyntax(
948+
let lifetimeSpecifier = RawLifetimeTypeSpecifierSyntax(
949+
unexpectedBeforeDependsOnKeyword,
950+
dependsOnKeyword: dependsOnKeyword,
951951
leftParen: leftParen,
952+
scopedKeyword: scoped,
952953
arguments: lifetimeSpecifierArgumentList,
953954
unexpectedBeforeRightParen,
954955
rightParen: rightParen,
955956
arena: self.arena
956957
)
957-
let lifetimeSpecifier = RawLifetimeTypeSpecifierSyntax(
958-
specifier: specifier,
959-
arguments: argumentsSyntax,
960-
arena: self.arena
961-
)
962958
return .lifetimeTypeSpecifier(lifetimeSpecifier)
963959
}
964960

@@ -976,20 +972,18 @@ extension Parser {
976972
specifiers: RawTypeSpecifierListSyntax,
977973
attributes: RawAttributeListSyntax
978974
)? {
979-
typealias SimpleOrLifetimeSpecifier =
980-
EitherTokenSpecSet<SimpleTypeSpecifierSyntax.SpecifierOptions, LifetimeTypeSpecifierSyntax.SpecifierOptions>
981975
var specifiers: [RawTypeSpecifierListSyntax.Element] = []
982-
SPECIFIER_PARSING: while canHaveParameterSpecifier,
983-
let (specifierSpec, specifierHandle) = self.at(anyIn: SimpleOrLifetimeSpecifier.self)
984-
{
985-
switch specifierSpec {
986-
case .lhs: specifiers.append(parseSimpleTypeSpecifier(specifierHandle: specifierHandle))
987-
case .rhs:
976+
SPECIFIER_PARSING: while canHaveParameterSpecifier {
977+
if let (_, specifierHandle) = self.at(anyIn: SimpleTypeSpecifierSyntax.SpecifierOptions.self) {
978+
specifiers.append(parseSimpleTypeSpecifier(specifierHandle: specifierHandle))
979+
} else if self.at(.keyword(.dependsOn)) {
988980
if self.experimentalFeatures.contains(.nonescapableTypes) {
989-
specifiers.append(parseLifetimeTypeSpecifier(specifierHandle: specifierHandle))
981+
specifiers.append(parseLifetimeTypeSpecifier())
990982
} else {
991983
break SPECIFIER_PARSING
992984
}
985+
} else {
986+
break SPECIFIER_PARSING
993987
}
994988
}
995989
specifiers += misplacedSpecifiers.map {

Sources/SwiftParser/generated/Parser+TokenSpecSet.swift

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,79 +2623,6 @@ extension LifetimeSpecifierArgumentSyntax {
26232623
}
26242624
}
26252625

2626-
extension LifetimeTypeSpecifierSyntax {
2627-
@_spi(Diagnostics)
2628-
public enum SpecifierOptions: TokenSpecSet {
2629-
@_spi(ExperimentalLanguageFeatures)
2630-
case _copy
2631-
@_spi(ExperimentalLanguageFeatures)
2632-
case _consume
2633-
case _borrow
2634-
@_spi(ExperimentalLanguageFeatures)
2635-
case _mutate
2636-
2637-
init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
2638-
switch PrepareForKeywordMatch(lexeme) {
2639-
case TokenSpec(._copy) where experimentalFeatures.contains(.nonescapableTypes):
2640-
self = ._copy
2641-
case TokenSpec(._consume) where experimentalFeatures.contains(.nonescapableTypes):
2642-
self = ._consume
2643-
case TokenSpec(._borrow):
2644-
self = ._borrow
2645-
case TokenSpec(._mutate) where experimentalFeatures.contains(.nonescapableTypes):
2646-
self = ._mutate
2647-
default:
2648-
return nil
2649-
}
2650-
}
2651-
2652-
public init?(token: TokenSyntax) {
2653-
switch token {
2654-
case TokenSpec(._copy):
2655-
self = ._copy
2656-
case TokenSpec(._consume):
2657-
self = ._consume
2658-
case TokenSpec(._borrow):
2659-
self = ._borrow
2660-
case TokenSpec(._mutate):
2661-
self = ._mutate
2662-
default:
2663-
return nil
2664-
}
2665-
}
2666-
2667-
var spec: TokenSpec {
2668-
switch self {
2669-
case ._copy:
2670-
return .keyword(._copy)
2671-
case ._consume:
2672-
return .keyword(._consume)
2673-
case ._borrow:
2674-
return .keyword(._borrow)
2675-
case ._mutate:
2676-
return .keyword(._mutate)
2677-
}
2678-
}
2679-
2680-
/// Returns a token that satisfies the `TokenSpec` of this case.
2681-
///
2682-
/// If the token kind of this spec has variable text, e.g. for an identifier, this returns a token with empty text.
2683-
@_spi(Diagnostics)
2684-
public var tokenSyntax: TokenSyntax {
2685-
switch self {
2686-
case ._copy:
2687-
return .keyword(._copy)
2688-
case ._consume:
2689-
return .keyword(._consume)
2690-
case ._borrow:
2691-
return .keyword(._borrow)
2692-
case ._mutate:
2693-
return .keyword(._mutate)
2694-
}
2695-
}
2696-
}
2697-
}
2698-
26992626
extension MemberTypeSyntax {
27002627
@_spi(Diagnostics)
27012628
public enum NameOptions: TokenSpecSet {

Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,30 +2009,28 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
20092009
return "trailingComma"
20102010
case \LifetimeSpecifierArgumentSyntax.unexpectedAfterTrailingComma:
20112011
return "unexpectedAfterTrailingComma"
2012-
case \LifetimeSpecifierArgumentsSyntax.unexpectedBeforeLeftParen:
2013-
return "unexpectedBeforeLeftParen"
2014-
case \LifetimeSpecifierArgumentsSyntax.leftParen:
2012+
case \LifetimeTypeSpecifierSyntax.unexpectedBeforeDependsOnKeyword:
2013+
return "unexpectedBeforeDependsOnKeyword"
2014+
case \LifetimeTypeSpecifierSyntax.dependsOnKeyword:
2015+
return "dependsOnKeyword"
2016+
case \LifetimeTypeSpecifierSyntax.unexpectedBetweenDependsOnKeywordAndLeftParen:
2017+
return "unexpectedBetweenDependsOnKeywordAndLeftParen"
2018+
case \LifetimeTypeSpecifierSyntax.leftParen:
20152019
return "leftParen"
2016-
case \LifetimeSpecifierArgumentsSyntax.unexpectedBetweenLeftParenAndArguments:
2017-
return "unexpectedBetweenLeftParenAndArguments"
2018-
case \LifetimeSpecifierArgumentsSyntax.arguments:
2020+
case \LifetimeTypeSpecifierSyntax.unexpectedBetweenLeftParenAndScopedKeyword:
2021+
return "unexpectedBetweenLeftParenAndScopedKeyword"
2022+
case \LifetimeTypeSpecifierSyntax.scopedKeyword:
2023+
return "scopedKeyword"
2024+
case \LifetimeTypeSpecifierSyntax.unexpectedBetweenScopedKeywordAndArguments:
2025+
return "unexpectedBetweenScopedKeywordAndArguments"
2026+
case \LifetimeTypeSpecifierSyntax.arguments:
20192027
return "arguments"
2020-
case \LifetimeSpecifierArgumentsSyntax.unexpectedBetweenArgumentsAndRightParen:
2028+
case \LifetimeTypeSpecifierSyntax.unexpectedBetweenArgumentsAndRightParen:
20212029
return "unexpectedBetweenArgumentsAndRightParen"
2022-
case \LifetimeSpecifierArgumentsSyntax.rightParen:
2030+
case \LifetimeTypeSpecifierSyntax.rightParen:
20232031
return "rightParen"
2024-
case \LifetimeSpecifierArgumentsSyntax.unexpectedAfterRightParen:
2032+
case \LifetimeTypeSpecifierSyntax.unexpectedAfterRightParen:
20252033
return "unexpectedAfterRightParen"
2026-
case \LifetimeTypeSpecifierSyntax.unexpectedBeforeSpecifier:
2027-
return "unexpectedBeforeSpecifier"
2028-
case \LifetimeTypeSpecifierSyntax.specifier:
2029-
return "specifier"
2030-
case \LifetimeTypeSpecifierSyntax.unexpectedBetweenSpecifierAndArguments:
2031-
return "unexpectedBetweenSpecifierAndArguments"
2032-
case \LifetimeTypeSpecifierSyntax.arguments:
2033-
return "arguments"
2034-
case \LifetimeTypeSpecifierSyntax.unexpectedAfterArguments:
2035-
return "unexpectedAfterArguments"
20362034
case \MacroDeclSyntax.unexpectedBeforeAttributes:
20372035
return "unexpectedBeforeAttributes"
20382036
case \MacroDeclSyntax.attributes:

0 commit comments

Comments
 (0)