Skip to content

Commit 13c82c6

Browse files
committed
Remove "unsafe" keyword from expressions when printing inlinable code
To help older compilers that don't yet support the unsafe expression deal with the Swift interface files we produce, remove the "unsafe" from expressions in inlinable code.
1 parent c0fb9f9 commit 13c82c6

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

lib/ASTGen/Sources/ASTGen/CompilerBuildConfiguration.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import ASTBridging
1414
import SwiftDiagnostics
1515
@_spi(Compiler) import SwiftIfConfig
16-
import SwiftParser
17-
import SwiftSyntax
16+
@_spi(ExperimentalLanguageFeatures) import SwiftParser
17+
@_spi(ExperimentalLanguageFeatures) import SwiftSyntax
1818

1919
/// A build configuration that uses the compiler's ASTContext to answer
2020
/// queries.
@@ -517,7 +517,11 @@ public func extractInlinableText(
517517
sourceText: BridgedStringRef
518518
) -> BridgedStringRef {
519519
let textBuffer = UnsafeBufferPointer<UInt8>(start: sourceText.data, count: sourceText.count)
520-
var parser = Parser(textBuffer)
520+
var parser = Parser(
521+
textBuffer,
522+
swiftVersion: Parser.SwiftVersion(from: astContext),
523+
experimentalFeatures: Parser.ExperimentalFeatures(from: astContext)
524+
)
521525
let syntax = SourceFileSyntax.parse(from: &parser)
522526

523527
let configuration = CompilerBuildConfiguration(
@@ -531,6 +535,24 @@ public func extractInlinableText(
531535
retainFeatureCheckIfConfigs: true
532536
).result
533537

538+
// Remove "unsafe" expressions.
539+
let inlineableSyntax = syntaxWithoutInactive.withoutUnsafeExpressions
540+
534541
// Remove comments and return the result.
535-
return allocateBridgedString(syntaxWithoutInactive.descriptionWithoutCommentsAndSourceLocations)
542+
return allocateBridgedString(inlineableSyntax.descriptionWithoutCommentsAndSourceLocations)
543+
}
544+
545+
/// Used by withoutUnsafeExpressions to remove "unsafe" expressions from
546+
/// a syntax tree.
547+
fileprivate class RemoveUnsafeExprSyntaxRewriter: SyntaxRewriter {
548+
override func visit(_ node: UnsafeExprSyntax) -> ExprSyntax {
549+
return node.expression.with(\.leadingTrivia, node.leadingTrivia)
550+
}
551+
}
552+
553+
extension SyntaxProtocol {
554+
/// Return a new syntax tree with all "unsafe" expressions removed.
555+
var withoutUnsafeExpressions: Syntax {
556+
RemoveUnsafeExprSyntaxRewriter().rewrite(self)
557+
}
536558
}

test/Unsafe/module-interface.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name UserModule -enable-experimental-feature AllowUnsafeAttribute -enable-experimental-feature WarnUnsafe
2+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name UserModule
3+
// RUN: %FileCheck %s < %t.swiftinterface
4+
5+
// REQUIRES: swift_feature_AllowUnsafeAttribute
6+
// REQUIRES: swift_feature_WarnUnsafe
7+
8+
// CHECK: #if compiler(>=5.3) && $AllowUnsafeAttribute
9+
// CHECK: @unsafe public func getIntUnsafely() -> Swift.Int
10+
// CHECK: #else
11+
// CHECK: public func getIntUnsafely() -> Swift.Int
12+
// CHECK: #endif
13+
@unsafe public func getIntUnsafely() -> Int { 0 }
14+
15+
// CHECK: @inlinable public func useUnsafeCode()
16+
@inlinable public func useUnsafeCode() {
17+
// CHECK-NOT: unsafe
18+
print( unsafe getIntUnsafely())
19+
}
20+
21+
// CHECK: public protocol P
22+
public protocol P {
23+
func f()
24+
}
25+
26+
// CHECK: public struct X : @unsafe UserModule.P
27+
public struct X: @unsafe P {
28+
// CHECK: #if compiler(>=5.3) && $AllowUnsafeAttribute
29+
// CHECK: @unsafe public func f()
30+
// CHECK: #else
31+
// CHECK: public func f()
32+
// CHECK: #endif
33+
@unsafe public func f() { }
34+
}

0 commit comments

Comments
 (0)