Skip to content

Commit 2f1a271

Browse files
authored
Merge pull request #2937 from DougGregor/unsafe-expression
2 parents 37fa0c8 + 68852dc commit 2f1a271

20 files changed

+403
-7
lines changed

CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public enum ExperimentalFeature: String, CaseIterable {
2121
case coroutineAccessors
2222
case valueGenerics
2323
case abiAttribute
24+
case unsafeExpression
2425

2526
/// The name of the feature as it is written in the compiler's `Features.def` file.
2627
public var featureName: String {
@@ -41,6 +42,8 @@ public enum ExperimentalFeature: String, CaseIterable {
4142
return "ValueGenerics"
4243
case .abiAttribute:
4344
return "ABIAttribute"
45+
case .unsafeExpression:
46+
return "WarnUnsafe"
4447
}
4548
}
4649

@@ -63,6 +66,8 @@ public enum ExperimentalFeature: String, CaseIterable {
6366
return "value generics"
6467
case .abiAttribute:
6568
return "@abi attribute"
69+
case .unsafeExpression:
70+
return "'unsafe' expression"
6671
}
6772
}
6873

CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,23 @@ public let EXPR_NODES: [Node] = [
180180
]
181181
),
182182

183+
Node(
184+
kind: .unsafeExpr,
185+
base: .expr,
186+
experimentalFeature: .unsafeExpression,
187+
nameForDiagnostics: "'unsafe' expression",
188+
children: [
189+
Child(
190+
name: "unsafeKeyword",
191+
kind: .token(choices: [.keyword(.unsafe)])
192+
),
193+
Child(
194+
name: "expression",
195+
kind: .node(kind: .expr)
196+
),
197+
]
198+
),
199+
183200
Node(
184201
kind: .binaryOperatorExpr,
185202
base: .expr,

CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
299299
case unresolvedAsExpr
300300
case unresolvedIsExpr
301301
case unresolvedTernaryExpr
302+
case unsafeExpr
302303
case valueBindingPattern
303304
case variableDecl
304305
case versionComponent

Sources/SwiftOperators/OperatorTable+Folding.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if compiler(>=6)
14-
public import SwiftSyntax
14+
@_spi(ExperimentalLanguageFeatures) public import SwiftSyntax
1515
#else
16-
import SwiftSyntax
16+
@_spi(ExperimentalLanguageFeatures) import SwiftSyntax
1717
#endif
1818

1919
extension ExprSyntax {
@@ -104,8 +104,8 @@ extension OperatorTable {
104104
op: ExprSyntax,
105105
rhs: ExprSyntax
106106
) -> ExprSyntax {
107-
// If the left-hand side is a "try" or "await", hoist it up to encompass
108-
// the right-hand side as well.
107+
// If the left-hand side is a "try", "await", or "unsafe", hoist it up to
108+
// encompass the right-hand side as well.
109109
if let tryExpr = lhs.as(TryExprSyntax.self) {
110110
return ExprSyntax(
111111
TryExprSyntax(
@@ -138,6 +138,24 @@ extension OperatorTable {
138138
)
139139
}
140140

141+
if let unsafeExpr = lhs.as(UnsafeExprSyntax.self) {
142+
return ExprSyntax(
143+
UnsafeExprSyntax(
144+
leadingTrivia: unsafeExpr.leadingTrivia,
145+
unsafeExpr.unexpectedBeforeUnsafeKeyword,
146+
unsafeKeyword: unsafeExpr.unsafeKeyword,
147+
unsafeExpr.unexpectedBetweenUnsafeKeywordAndExpression,
148+
expression: makeBinaryOperationExpr(
149+
lhs: unsafeExpr.expression,
150+
op: op,
151+
rhs: rhs
152+
),
153+
unsafeExpr.unexpectedAfterExpression,
154+
trailingTrivia: unsafeExpr.trailingTrivia
155+
)
156+
)
157+
}
158+
141159
// The form of the binary operation depends on the operator itself,
142160
// which will be one of the unresolved infix operators.
143161

Sources/SwiftParser/Expressions.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,19 @@ extension Parser {
444444
arena: self.arena
445445
)
446446
)
447+
case (.unsafe, let handle)?:
448+
let unsafeTok = self.eat(handle)
449+
let sub = self.parseSequenceExpressionElement(
450+
flavor: flavor,
451+
pattern: pattern
452+
)
453+
return RawExprSyntax(
454+
RawUnsafeExprSyntax(
455+
unsafeKeyword: unsafeTok,
456+
expression: sub,
457+
arena: self.arena
458+
)
459+
)
447460
case (._move, let handle)?:
448461
let moveKeyword = self.eat(handle)
449462
let sub = self.parseSequenceExpressionElement(

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
700700
case `repeat`
701701
case each
702702
case any
703+
case unsafe
703704

704705
init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
705706
switch PrepareForKeywordMatch(lexeme) {
@@ -713,6 +714,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
713714
case TokenSpec(.repeat): self = .repeat
714715
case TokenSpec(.each): self = .each
715716
case TokenSpec(.any): self = .any
717+
case TokenSpec(.unsafe) where experimentalFeatures.contains(.unsafeExpression): self = .unsafe
716718
default: return nil
717719
}
718720
}
@@ -729,6 +731,7 @@ enum ExpressionModifierKeyword: TokenSpecSet {
729731
case .repeat: return .keyword(.repeat)
730732
case .each: return .keyword(.each)
731733
case .any: return .keyword(.any)
734+
case .unsafe: return .keyword(.unsafe)
732735
}
733736
}
734737
}

Sources/SwiftParser/generated/ExperimentalFeatures.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ extension Parser.ExperimentalFeatures {
4848
/// Whether to enable the parsing of @abi attribute.
4949
public static let abiAttribute = Self (rawValue: 1 << 7)
5050

51+
/// Whether to enable the parsing of 'unsafe' expression.
52+
public static let unsafeExpression = Self (rawValue: 1 << 8)
53+
5154
/// Creates a new value representing the experimental feature with the
5255
/// given name, or returns nil if the name is not recognized.
5356
public init?(name: String) {
@@ -68,6 +71,8 @@ extension Parser.ExperimentalFeatures {
6871
self = .valueGenerics
6972
case "ABIAttribute":
7073
self = .abiAttribute
74+
case "WarnUnsafe":
75+
self = .unsafeExpression
7176
default:
7277
return nil
7378
}

Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ extension SyntaxKind {
399399
return "'is'"
400400
case .unresolvedTernaryExpr:
401401
return "ternary operator"
402+
case .unsafeExpr:
403+
return "'unsafe' expression"
402404
case .valueBindingPattern:
403405
return "value binding pattern"
404406
case .variableDecl:

Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3387,6 +3387,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
33873387
return "colon"
33883388
case \UnresolvedTernaryExprSyntax.unexpectedAfterColon:
33893389
return "unexpectedAfterColon"
3390+
case \UnsafeExprSyntax.unexpectedBeforeUnsafeKeyword:
3391+
return "unexpectedBeforeUnsafeKeyword"
3392+
case \UnsafeExprSyntax.unsafeKeyword:
3393+
return "unsafeKeyword"
3394+
case \UnsafeExprSyntax.unexpectedBetweenUnsafeKeywordAndExpression:
3395+
return "unexpectedBetweenUnsafeKeywordAndExpression"
3396+
case \UnsafeExprSyntax.expression:
3397+
return "expression"
3398+
case \UnsafeExprSyntax.unexpectedAfterExpression:
3399+
return "unexpectedAfterExpression"
33903400
case \ValueBindingPatternSyntax.unexpectedBeforeBindingSpecifier:
33913401
return "unexpectedBeforeBindingSpecifier"
33923402
case \ValueBindingPatternSyntax.bindingSpecifier:

Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,6 +2268,20 @@ open class SyntaxAnyVisitor: SyntaxVisitor {
22682268
visitAnyPost(node._syntaxNode)
22692269
}
22702270

2271+
#if compiler(>=5.8)
2272+
@_spi(ExperimentalLanguageFeatures)
2273+
#endif
2274+
override open func visit(_ node: UnsafeExprSyntax) -> SyntaxVisitorContinueKind {
2275+
return visitAny(node._syntaxNode)
2276+
}
2277+
2278+
#if compiler(>=5.8)
2279+
@_spi(ExperimentalLanguageFeatures)
2280+
#endif
2281+
override open func visitPost(_ node: UnsafeExprSyntax) {
2282+
visitAnyPost(node._syntaxNode)
2283+
}
2284+
22712285
override open func visit(_ node: ValueBindingPatternSyntax) -> SyntaxVisitorContinueKind {
22722286
return visitAny(node._syntaxNode)
22732287
}

Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift

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

543543
public init?(_ node: __shared some SyntaxProtocol) {
544544
switch node.raw.kind {
545-
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, ._canImportExpr, ._canImportVersionInfo, .closureExpr, .consumeExpr, .copyExpr, .declReferenceExpr, .dictionaryExpr, .discardAssignmentExpr, .doExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forceUnwrapExpr, .functionCallExpr, .genericSpecializationExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .patternExpr, .postfixIfConfigExpr, .postfixOperatorExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .simpleStringLiteralExpr, .stringLiteralExpr, .subscriptCallExpr, .superExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedTernaryExpr:
545+
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, ._canImportExpr, ._canImportVersionInfo, .closureExpr, .consumeExpr, .copyExpr, .declReferenceExpr, .dictionaryExpr, .discardAssignmentExpr, .doExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forceUnwrapExpr, .functionCallExpr, .genericSpecializationExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .patternExpr, .postfixIfConfigExpr, .postfixOperatorExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .simpleStringLiteralExpr, .stringLiteralExpr, .subscriptCallExpr, .superExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedTernaryExpr, .unsafeExpr:
546546
self._syntaxNode = node._syntaxNode
547547
default:
548548
return nil
@@ -619,7 +619,8 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
619619
.node(TypeExprSyntax.self),
620620
.node(UnresolvedAsExprSyntax.self),
621621
.node(UnresolvedIsExprSyntax.self),
622-
.node(UnresolvedTernaryExprSyntax.self)
622+
.node(UnresolvedTernaryExprSyntax.self),
623+
.node(UnsafeExprSyntax.self)
623624
])
624625
}
625626
}
@@ -1789,6 +1790,7 @@ extension Syntax {
17891790
.node(UnresolvedAsExprSyntax.self),
17901791
.node(UnresolvedIsExprSyntax.self),
17911792
.node(UnresolvedTernaryExprSyntax.self),
1793+
.node(UnsafeExprSyntax.self),
17921794
.node(ValueBindingPatternSyntax.self),
17931795
.node(VariableDeclSyntax.self),
17941796
.node(VersionComponentListSyntax.self),

Sources/SwiftSyntax/generated/SyntaxEnum.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ public enum SyntaxEnum: Sendable {
305305
case unresolvedAsExpr(UnresolvedAsExprSyntax)
306306
case unresolvedIsExpr(UnresolvedIsExprSyntax)
307307
case unresolvedTernaryExpr(UnresolvedTernaryExprSyntax)
308+
#if compiler(>=5.8)
309+
@_spi(ExperimentalLanguageFeatures)
310+
#endif
311+
case unsafeExpr(UnsafeExprSyntax)
308312
case valueBindingPattern(ValueBindingPatternSyntax)
309313
case variableDecl(VariableDeclSyntax)
310314
case versionComponentList(VersionComponentListSyntax)
@@ -869,6 +873,8 @@ extension Syntax {
869873
return .unresolvedIsExpr(UnresolvedIsExprSyntax(self)!)
870874
case .unresolvedTernaryExpr:
871875
return .unresolvedTernaryExpr(UnresolvedTernaryExprSyntax(self)!)
876+
case .unsafeExpr:
877+
return .unsafeExpr(UnsafeExprSyntax(self)!)
872878
case .valueBindingPattern:
873879
return .valueBindingPattern(ValueBindingPatternSyntax(self)!)
874880
case .variableDecl:
@@ -1041,6 +1047,10 @@ public enum ExprSyntaxEnum {
10411047
case unresolvedAsExpr(UnresolvedAsExprSyntax)
10421048
case unresolvedIsExpr(UnresolvedIsExprSyntax)
10431049
case unresolvedTernaryExpr(UnresolvedTernaryExprSyntax)
1050+
#if compiler(>=5.8)
1051+
@_spi(ExperimentalLanguageFeatures)
1052+
#endif
1053+
case unsafeExpr(UnsafeExprSyntax)
10441054
}
10451055

10461056
extension ExprSyntax {
@@ -1153,6 +1163,8 @@ extension ExprSyntax {
11531163
return .unresolvedIsExpr(UnresolvedIsExprSyntax(self)!)
11541164
case .unresolvedTernaryExpr:
11551165
return .unresolvedTernaryExpr(UnresolvedTernaryExprSyntax(self)!)
1166+
case .unsafeExpr:
1167+
return .unsafeExpr(UnsafeExprSyntax(self)!)
11561168
default:
11571169
preconditionFailure("unknown Expr syntax kind")
11581170
}

Sources/SwiftSyntax/generated/SyntaxKind.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ public enum SyntaxKind: Sendable {
305305
case unresolvedAsExpr
306306
case unresolvedIsExpr
307307
case unresolvedTernaryExpr
308+
#if compiler(>=5.8)
309+
@_spi(ExperimentalLanguageFeatures)
310+
#endif
311+
case unsafeExpr
308312
case valueBindingPattern
309313
case variableDecl
310314
case versionComponentList
@@ -994,6 +998,8 @@ public enum SyntaxKind: Sendable {
994998
return UnresolvedIsExprSyntax.self
995999
case .unresolvedTernaryExpr:
9961000
return UnresolvedTernaryExprSyntax.self
1001+
case .unsafeExpr:
1002+
return UnsafeExprSyntax.self
9971003
case .valueBindingPattern:
9981004
return ValueBindingPatternSyntax.self
9991005
case .variableDecl:

Sources/SwiftSyntax/generated/SyntaxRewriter.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,6 +2020,16 @@ open class SyntaxRewriter {
20202020
return ExprSyntax(UnresolvedTernaryExprSyntax(unsafeCasting: visitChildren(node._syntaxNode)))
20212021
}
20222022

2023+
/// Visit a `UnsafeExprSyntax`.
2024+
/// - Parameter node: the node that is being visited
2025+
/// - Returns: the rewritten node
2026+
#if compiler(>=5.8)
2027+
@_spi(ExperimentalLanguageFeatures)
2028+
#endif
2029+
open func visit(_ node: UnsafeExprSyntax) -> ExprSyntax {
2030+
return ExprSyntax(UnsafeExprSyntax(unsafeCasting: visitChildren(node._syntaxNode)))
2031+
}
2032+
20232033
/// Visit a ``ValueBindingPatternSyntax``.
20242034
/// - Parameter node: the node that is being visited
20252035
/// - Returns: the rewritten node
@@ -3504,6 +3514,11 @@ open class SyntaxRewriter {
35043514
Syntax(visit(UnresolvedTernaryExprSyntax(unsafeCasting: node)))
35053515
}
35063516

3517+
@inline(never)
3518+
private func visitUnsafeExprSyntaxImpl(_ node: Syntax) -> Syntax {
3519+
Syntax(visit(UnsafeExprSyntax(unsafeCasting: node)))
3520+
}
3521+
35073522
@inline(never)
35083523
private func visitValueBindingPatternSyntaxImpl(_ node: Syntax) -> Syntax {
35093524
Syntax(visit(ValueBindingPatternSyntax(unsafeCasting: node)))
@@ -4136,6 +4151,8 @@ open class SyntaxRewriter {
41364151
return self.visitUnresolvedIsExprSyntaxImpl(_:)
41374152
case .unresolvedTernaryExpr:
41384153
return self.visitUnresolvedTernaryExprSyntaxImpl(_:)
4154+
case .unsafeExpr:
4155+
return self.visitUnsafeExprSyntaxImpl(_:)
41394156
case .valueBindingPattern:
41404157
return self.visitValueBindingPatternSyntaxImpl(_:)
41414158
case .variableDecl:
@@ -4714,6 +4731,8 @@ open class SyntaxRewriter {
47144731
return visitUnresolvedIsExprSyntaxImpl(node)
47154732
case .unresolvedTernaryExpr:
47164733
return visitUnresolvedTernaryExprSyntaxImpl(node)
4734+
case .unsafeExpr:
4735+
return visitUnsafeExprSyntaxImpl(node)
47174736
case .valueBindingPattern:
47184737
return visitValueBindingPatternSyntaxImpl(node)
47194738
case .variableDecl:

0 commit comments

Comments
 (0)