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
}

0 commit comments

Comments
 (0)