Skip to content

Commit a700b4d

Browse files
committed
Add support for @Lifetime(borrow ...)
1 parent 38459d4 commit a700b4d

File tree

10 files changed

+101
-6
lines changed

10 files changed

+101
-6
lines changed

CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public let EXPR_NODES: [Node] = [
228228
children: [
229229
Child(
230230
name: "borrowKeyword",
231-
kind: .token(choices: [.keyword(._borrow)])
231+
kind: .token(choices: [.keyword(._borrow), .keyword(.borrow)])
232232
),
233233
Child(
234234
name: "expression",

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ public enum Keyword: CaseIterable {
150150
case backDeployed
151151
case before
152152
case block
153+
case borrow
153154
case borrowing
154155
case `break`
155156
case canImport
@@ -442,6 +443,8 @@ public enum Keyword: CaseIterable {
442443
return KeywordSpec("before")
443444
case .block:
444445
return KeywordSpec("block")
446+
case .borrow:
447+
return KeywordSpec("borrow")
445448
case .borrowing:
446449
return KeywordSpec("borrowing")
447450
case .break:

Sources/SwiftParser/Expressions.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,11 @@ extension Parser {
458458
)
459459
)
460460
case (._borrow, let handle)?:
461+
fallthrough
462+
case (.borrow, let handle)?:
463+
if !atContextualExpressionModifier() {
464+
break EXPR_PREFIX
465+
}
461466
let borrowTok = self.eat(handle)
462467
let sub = self.parseSequenceExpressionElement(
463468
flavor: flavor,

Sources/SwiftParser/TokenPrecedence.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ enum TokenPrecedence: Comparable {
235235
.__consuming, .final, .required, .optional, .lazy, .dynamic, .infix, .postfix, .prefix, .mutating, .nonmutating,
236236
.convenience, .override, .package, .open,
237237
.__setter_access, .indirect, .isolated, .nonisolated, .distributed, ._local,
238-
.inout, ._mutating, ._borrow, ._borrowing, .borrowing, ._consuming, .consuming, .consume,
238+
.inout, ._mutating, ._borrow, ._borrowing, .borrow, .borrowing, ._consuming, .consuming, .consume,
239239
.dependsOn, .scoped, .sending,
240240
// Accessors
241241
.get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress,

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
694694
case _move
695695
case _borrow
696696
case `try`
697+
case borrow
697698
case consume
698699
case copy
699700
case `repeat`
@@ -706,6 +707,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
706707
case TokenSpec(._move): self = ._move
707708
case TokenSpec(._borrow): self = ._borrow
708709
case TokenSpec(.try): self = .try
710+
case TokenSpec(.borrow): self = .borrow
709711
case TokenSpec(.consume): self = .consume
710712
case TokenSpec(.copy): self = .copy
711713
case TokenSpec(.repeat): self = .repeat
@@ -720,6 +722,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
720722
case .await: return .keyword(.await)
721723
case ._move: return .keyword(._move)
722724
case ._borrow: return .keyword(._borrow)
725+
case .borrow: return .keyword(.borrow)
723726
case .consume: return .keyword(.consume)
724727
case .copy: return .keyword(.copy)
725728
case .try: return .keyword(.try)

Sources/SwiftParser/generated/Parser+TokenSpecSet.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,58 @@ extension BooleanLiteralExprSyntax {
428428
}
429429
}
430430

431+
extension BorrowExprSyntax {
432+
@_spi(Diagnostics)
433+
public enum BorrowKeywordOptions: TokenSpecSet {
434+
case _borrow
435+
case borrow
436+
437+
init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
438+
switch PrepareForKeywordMatch(lexeme) {
439+
case TokenSpec(._borrow):
440+
self = ._borrow
441+
case TokenSpec(.borrow):
442+
self = .borrow
443+
default:
444+
return nil
445+
}
446+
}
447+
448+
public init?(token: TokenSyntax) {
449+
switch token {
450+
case TokenSpec(._borrow):
451+
self = ._borrow
452+
case TokenSpec(.borrow):
453+
self = .borrow
454+
default:
455+
return nil
456+
}
457+
}
458+
459+
var spec: TokenSpec {
460+
switch self {
461+
case ._borrow:
462+
return .keyword(._borrow)
463+
case .borrow:
464+
return .keyword(.borrow)
465+
}
466+
}
467+
468+
/// Returns a token that satisfies the `TokenSpec` of this case.
469+
///
470+
/// If the token kind of this spec has variable text, e.g. for an identifier, this returns a token with empty text.
471+
@_spi(Diagnostics)
472+
public var tokenSyntax: TokenSyntax {
473+
switch self {
474+
case ._borrow:
475+
return .keyword(._borrow)
476+
case .borrow:
477+
return .keyword(.borrow)
478+
}
479+
}
480+
}
481+
}
482+
431483
extension _CanImportVersionInfoSyntax {
432484
@_spi(Diagnostics)
433485
public enum LabelOptions: TokenSpecSet {

Sources/SwiftSyntax/generated/Keyword.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public enum Keyword: UInt8, Hashable, Sendable {
9090
case backDeployed
9191
case before
9292
case block
93+
case borrow
9394
case borrowing
9495
case `break`
9596
case canImport
@@ -416,6 +417,8 @@ public enum Keyword: UInt8, Hashable, Sendable {
416417
self = ._local
417418
case "before":
418419
self = .before
420+
case "borrow":
421+
self = .borrow
419422
case "deinit":
420423
self = .deinit
421424
case "didSet":
@@ -890,6 +893,7 @@ public enum Keyword: UInt8, Hashable, Sendable {
890893
"backDeployed",
891894
"before",
892895
"block",
896+
"borrow",
893897
"borrowing",
894898
"break",
895899
"canImport",

Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) {
455455
case .borrowExpr:
456456
assert(layout.count == 5)
457457
assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self))
458-
assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.keyword("_borrow")]))
458+
assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.keyword("_borrow"), .keyword("borrow")]))
459459
assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self))
460460
assertNoError(kind, 3, verify(layout[3], as: RawExprSyntax.self))
461461
assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self))

Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4497,7 +4497,7 @@ public struct BooleanLiteralExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea
44974497

44984498
/// ### Children
44994499
///
4500-
/// - `borrowKeyword`: `_borrow`
4500+
/// - `borrowKeyword`: (`_borrow` | `borrow`)
45014501
/// - `expression`: ``ExprSyntax``
45024502
public struct BorrowExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSyntaxNodeProtocol {
45034503
public let _syntaxNode: Syntax
@@ -4515,7 +4515,7 @@ public struct BorrowExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSyn
45154515
public init(
45164516
leadingTrivia: Trivia? = nil,
45174517
_ unexpectedBeforeBorrowKeyword: UnexpectedNodesSyntax? = nil,
4518-
borrowKeyword: TokenSyntax = .keyword(._borrow),
4518+
borrowKeyword: TokenSyntax,
45194519
_ unexpectedBetweenBorrowKeywordAndExpression: UnexpectedNodesSyntax? = nil,
45204520
expression: some ExprSyntaxProtocol,
45214521
_ unexpectedAfterExpression: UnexpectedNodesSyntax? = nil,
@@ -4559,7 +4559,9 @@ public struct BorrowExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSyn
45594559

45604560
/// ### Tokens
45614561
///
4562-
/// For syntax trees generated by the parser, this is guaranteed to be `_borrow`.
4562+
/// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds:
4563+
/// - `_borrow`
4564+
/// - `borrow`
45634565
public var borrowKeyword: TokenSyntax {
45644566
get {
45654567
return Syntax(self).child(at: 1)!.cast(TokenSyntax.self)

Tests/SwiftParserTest/AttributeTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,4 +1053,30 @@ final class AttributeTests: ParserTestCase {
10531053
"""
10541054
)
10551055
}
1056+
1057+
func testLifetimeAttribute() {
1058+
assertParse(
1059+
"""
1060+
struct NE: ~Escapable {}
1061+
1062+
@lifetime(ne)
1063+
func derive1(ne: NE) -> NE { ne }
1064+
1065+
@lifetime(borrow ne)
1066+
func derive2(ne: borrowing NE) -> NE { ne }
1067+
1068+
@lifetime(ne1, n2)
1069+
func derive3(ne1: NE, ne2: NE) -> NE { ne1 }
1070+
1071+
@lifetime(borrow ne1, n2)
1072+
func derive4(ne1: NE, ne2: NE) -> NE { ne1 }
1073+
1074+
@lifetime(neOut: ne)
1075+
func derive5(ne: NE, neOut: inout NE) -> NE { neOut = ne }
1076+
1077+
@lifetime(neOut: borrow ne)
1078+
func derive6(ne: borrowing NE, neOut: inout NE) -> NE { neOut = ne }
1079+
"""
1080+
)
1081+
}
10561082
}

0 commit comments

Comments
 (0)