Skip to content

Commit d9b5a46

Browse files
committed
Enable strict memory safety in the Distributed module
1 parent 177d16c commit d9b5a46

7 files changed

+50
-48
lines changed

stdlib/public/Distributed/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ add_swift_target_library(swiftDistributed ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS
5252
SWIFT_COMPILE_FLAGS
5353
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
5454
-parse-stdlib
55+
-strict-memory-safety
5556

5657
LINK_FLAGS
5758
"${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"

stdlib/public/Distributed/DistributedActor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,10 @@ extension DistributedActor {
406406
@_implements(Actor, unownedExecutor)
407407
public nonisolated var __actorUnownedExecutor: UnownedSerialExecutor {
408408
if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {
409-
return unownedExecutor
409+
return unsafe unownedExecutor
410410
} else {
411411
// On older platforms, all distributed actors are default actors.
412-
return UnownedSerialExecutor(Builtin.buildDefaultActorExecutorRef(self))
412+
return unsafe UnownedSerialExecutor(Builtin.buildDefaultActorExecutorRef(self))
413413
}
414414
}
415415

stdlib/public/Distributed/DistributedActorSystem.swift

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ extension DistributedActorSystem {
438438

439439
// Gen the generic environment (if any) associated with the target.
440440
let genericEnv =
441-
targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
442-
_getGenericEnvironmentOfDistributedTarget(
441+
unsafe targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
442+
unsafe _getGenericEnvironmentOfDistributedTarget(
443443
targetNameUTF8.baseAddress!,
444444
UInt(targetNameUTF8.endIndex))
445445
}
@@ -449,26 +449,26 @@ extension DistributedActorSystem {
449449
var numWitnessTables: Int = 0
450450

451451
defer {
452-
substitutionsBuffer?.deallocate()
453-
witnessTablesBuffer?.deallocate()
452+
unsafe substitutionsBuffer?.deallocate()
453+
unsafe witnessTablesBuffer?.deallocate()
454454
}
455455

456-
if let genericEnv = genericEnv {
456+
if let genericEnv = unsafe genericEnv {
457457
let subs = try invocationDecoder.decodeGenericSubstitutions()
458458
if subs.isEmpty {
459459
throw ExecuteDistributedTargetError(
460460
message: "Cannot call generic method without generic argument substitutions",
461461
errorCode: .missingGenericSubstitutions)
462462
}
463463

464-
substitutionsBuffer = .allocate(capacity: subs.count)
464+
unsafe substitutionsBuffer = .allocate(capacity: subs.count)
465465

466466
for (offset, substitution) in subs.enumerated() {
467-
let element = substitutionsBuffer?.advanced(by: offset)
468-
element?.initialize(to: substitution)
467+
let element = unsafe substitutionsBuffer?.advanced(by: offset)
468+
unsafe element?.initialize(to: substitution)
469469
}
470470

471-
(witnessTablesBuffer, numWitnessTables) = _getWitnessTablesFor(environment: genericEnv,
471+
unsafe (witnessTablesBuffer, numWitnessTables) = unsafe _getWitnessTablesFor(environment: genericEnv,
472472
genericArguments: substitutionsBuffer!)
473473
if numWitnessTables < 0 {
474474
throw ExecuteDistributedTargetError(
@@ -478,8 +478,8 @@ extension DistributedActorSystem {
478478
}
479479

480480
let paramCount =
481-
targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
482-
__getParameterCount(
481+
unsafe targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
482+
unsafe __getParameterCount(
483483
targetNameUTF8.baseAddress!,
484484
UInt(targetNameUTF8.endIndex))
485485
}
@@ -497,12 +497,12 @@ extension DistributedActorSystem {
497497
// Prepare buffer for the parameter types to be decoded into:
498498
let argumentTypesBuffer = UnsafeMutableBufferPointer<Any.Type>.allocate(capacity: Int(paramCount))
499499
defer {
500-
argumentTypesBuffer.deallocate()
500+
unsafe argumentTypesBuffer.deallocate()
501501
}
502502

503503
// Demangle and write all parameter types into the prepared buffer
504-
let decodedNum = targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
505-
__getParameterTypeInfo(
504+
let decodedNum = unsafe targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
505+
unsafe __getParameterTypeInfo(
506506
targetNameUTF8.baseAddress!,
507507
UInt(targetNameUTF8.endIndex),
508508
genericEnv,
@@ -525,7 +525,7 @@ extension DistributedActorSystem {
525525
var argumentTypes: [Any.Type] = []
526526
do {
527527
argumentTypes.reserveCapacity(Int(decodedNum))
528-
for argumentType in argumentTypesBuffer {
528+
for unsafe argumentType in unsafe argumentTypesBuffer {
529529
argumentTypes.append(argumentType)
530530
}
531531
}
@@ -536,8 +536,8 @@ extension DistributedActorSystem {
536536
}
537537

538538
let maybeReturnTypeFromTypeInfo =
539-
targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
540-
__getReturnTypeInfo(
539+
unsafe targetNameUTF8.withUnsafeBufferPointer { targetNameUTF8 in
540+
unsafe __getReturnTypeInfo(
541541
/*targetName:*/targetNameUTF8.baseAddress!,
542542
/*targetLength:*/UInt(targetNameUTF8.endIndex),
543543
/*genericEnv:*/genericEnv,
@@ -549,7 +549,7 @@ extension DistributedActorSystem {
549549
errorCode: .typeDeserializationFailure)
550550
}
551551

552-
guard let resultBuffer = _openExistential(returnTypeFromTypeInfo, do: doAllocateReturnTypeBuffer) else {
552+
guard let resultBuffer = _openExistential(returnTypeFromTypeInfo, do: unsafe doAllocateReturnTypeBuffer) else {
553553
throw ExecuteDistributedTargetError(
554554
message: "Failed to allocate buffer for distributed target return type",
555555
errorCode: .typeDeserializationFailure)
@@ -560,16 +560,16 @@ extension DistributedActorSystem {
560560
var executeDistributedTargetHasThrown = true
561561

562562
func doDestroyReturnTypeBuffer<R>(_: R.Type) {
563-
let buf = resultBuffer.assumingMemoryBound(to: R.self)
563+
let buf = unsafe resultBuffer.assumingMemoryBound(to: R.self)
564564

565565
if !executeDistributedTargetHasThrown {
566566
// since the _execute function has NOT thrown,
567567
// there must be a value in the result buffer that we must deinitialize
568-
buf.deinitialize(count: 1)
568+
unsafe buf.deinitialize(count: 1)
569569
} // otherwise, the _execute has thrown and not populated the result buffer
570570

571571
// finally, deallocate the buffer
572-
buf.deallocate()
572+
unsafe buf.deallocate()
573573
}
574574

575575
defer {
@@ -581,7 +581,7 @@ extension DistributedActorSystem {
581581
// let errorType = try invocationDecoder.decodeErrorType() // TODO(distributed): decide how to use when typed throws are done
582582

583583
// Execute the target!
584-
try await _executeDistributedTarget(
584+
try unsafe await _executeDistributedTarget(
585585
on: actor,
586586
/*targetNameData:*/targetName,
587587
/*targetNameLength:*/UInt(targetName.count),
@@ -599,7 +599,7 @@ extension DistributedActorSystem {
599599
if returnType == Void.self {
600600
try await handler.onReturnVoid()
601601
} else {
602-
try await self.invokeHandlerOnReturn(
602+
try unsafe await self.invokeHandlerOnReturn(
603603
handler: handler,
604604
resultBuffer: resultBuffer,
605605
metatype: returnType

stdlib/public/Distributed/DistributedAssertions.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ extension DistributedActor {
5151
return
5252
}
5353

54-
let unownedExecutor = self.unownedExecutor
55-
let expectationCheck = _taskIsCurrentExecutor(unownedExecutor._executor)
54+
let unownedExecutor = unsafe self.unownedExecutor
55+
let expectationCheck = unsafe _taskIsCurrentExecutor(unownedExecutor._executor)
5656

5757
precondition(expectationCheck,
58-
"Incorrect actor executor assumption; Expected '\(self.unownedExecutor)' executor. \(message())",
58+
unsafe "Incorrect actor executor assumption; Expected '\(unsafe self.unownedExecutor)' executor. \(message())",
5959
file: file, line: line)
6060
}
6161
}
@@ -99,9 +99,9 @@ extension DistributedActor {
9999
return
100100
}
101101

102-
let unownedExecutor = self.unownedExecutor
103-
guard _taskIsCurrentExecutor(unownedExecutor._executor) else {
104-
let msg = "Incorrect actor executor assumption; Expected '\(unownedExecutor)' executor. \(message())"
102+
let unownedExecutor = unsafe self.unownedExecutor
103+
guard unsafe _taskIsCurrentExecutor(unownedExecutor._executor) else {
104+
let msg = unsafe "Incorrect actor executor assumption; Expected '\(unsafe unownedExecutor)' executor. \(message())"
105105
/// TODO: implement the logic in-place perhaps rather than delegating to precondition()?
106106
assertionFailure(msg, file: file, line: line) // short-cut so we get the exact same failure reporting semantics
107107
return
@@ -165,16 +165,16 @@ extension DistributedActor {
165165
fatalError("Cannot assume to be 'isolated \(Self.self)' since distributed actor '\(self)' is a remote actor reference.")
166166
}
167167

168-
let unownedExecutor = self.unownedExecutor
169-
guard _taskIsCurrentExecutor(unownedExecutor._executor) else {
168+
let unownedExecutor = unsafe self.unownedExecutor
169+
guard unsafe _taskIsCurrentExecutor(unownedExecutor._executor) else {
170170
// TODO: offer information which executor we actually got when
171171
fatalError("Incorrect actor executor assumption; Expected same executor as \(self).", file: file, line: line)
172172
}
173173

174174
// To do the unsafe cast, we have to pretend it's @escaping.
175175
return try withoutActuallyEscaping(operation) {
176176
(_ fn: @escaping YesActor) throws -> T in
177-
let rawFn = unsafeBitCast(fn, to: NoActor.self)
177+
let rawFn = unsafe unsafeBitCast(fn, to: NoActor.self)
178178
return try rawFn(self)
179179
}
180180
}

stdlib/public/Distributed/DistributedDefaultExecutor.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import _Concurrency
1818
internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
1919
static let _shared: DistributedRemoteActorReferenceExecutor = DistributedRemoteActorReferenceExecutor()
2020
static var sharedUnownedExecutor: UnownedSerialExecutor {
21-
UnownedSerialExecutor(ordinary: _shared)
21+
unsafe UnownedSerialExecutor(ordinary: _shared)
2222
}
2323

2424
internal init() {}
@@ -38,7 +38,7 @@ internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
3838
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
3939

4040
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
41-
UnownedSerialExecutor(ordinary: self)
41+
unsafe UnownedSerialExecutor(ordinary: self)
4242
}
4343
}
4444

@@ -57,5 +57,5 @@ internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
5757
public func buildDefaultDistributedRemoteActorExecutor<Act>(
5858
_ actor: Act
5959
) -> UnownedSerialExecutor where Act: DistributedActor {
60-
return DistributedRemoteActorReferenceExecutor.sharedUnownedExecutor
60+
return unsafe DistributedRemoteActorReferenceExecutor.sharedUnownedExecutor
6161
}

stdlib/public/Distributed/DistributedMetadata.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import Swift
1919
public // SPI Distributed
2020
func _getParameterCount(mangledMethodName name: String) -> Int32 {
2121
let nameUTF8 = Array(name.utf8)
22-
return nameUTF8.withUnsafeBufferPointer { nameUTF8 in
23-
return __getParameterCount(
22+
return unsafe nameUTF8.withUnsafeBufferPointer { nameUTF8 in
23+
return unsafe __getParameterCount(
2424
nameUTF8.baseAddress!, UInt(nameUTF8.endIndex))
2525
}
2626
}
@@ -47,8 +47,8 @@ func _getParameterTypeInfo(
4747
into typesBuffer: Builtin.RawPointer, length typesLength: Int
4848
) -> Int32 {
4949
let nameUTF8 = Array(name.utf8)
50-
return nameUTF8.withUnsafeBufferPointer { nameUTF8 in
51-
return __getParameterTypeInfo(
50+
return unsafe nameUTF8.withUnsafeBufferPointer { nameUTF8 in
51+
return unsafe __getParameterTypeInfo(
5252
nameUTF8.baseAddress!, UInt(nameUTF8.endIndex),
5353
genericEnv, genericArguments, typesBuffer, typesLength)
5454
}
@@ -75,8 +75,8 @@ func _getReturnTypeInfo(
7575
genericArguments: UnsafeRawPointer?
7676
) -> Any.Type? {
7777
let nameUTF8 = Array(name.utf8)
78-
return nameUTF8.withUnsafeBufferPointer { nameUTF8 in
79-
return __getReturnTypeInfo(nameUTF8.baseAddress!, UInt(nameUTF8.endIndex),
78+
return unsafe nameUTF8.withUnsafeBufferPointer { nameUTF8 in
79+
return unsafe __getReturnTypeInfo(nameUTF8.baseAddress!, UInt(nameUTF8.endIndex),
8080
genericEnv, genericArguments)
8181
}
8282
}

stdlib/public/Distributed/LocalTestingDistributedActorSystem.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ public struct LocalTestingDistributedActorSystemError: DistributedActorSystemErr
236236
// === lock ----------------------------------------------------------------
237237

238238
@available(SwiftStdlib 5.7, *)
239+
@safe
239240
fileprivate class _Lock {
240241
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
241242
private let underlying: UnsafeMutablePointer<os_unfair_lock>
@@ -252,7 +253,7 @@ fileprivate class _Lock {
252253
init() {
253254
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
254255
self.underlying = UnsafeMutablePointer.allocate(capacity: 1)
255-
self.underlying.initialize(to: os_unfair_lock())
256+
unsafe self.underlying.initialize(to: os_unfair_lock())
256257
#elseif os(Windows)
257258
self.underlying = UnsafeMutablePointer.allocate(capacity: 1)
258259
InitializeSRWLock(self.underlying)
@@ -280,16 +281,16 @@ fileprivate class _Lock {
280281
#endif
281282

282283
#if !os(WASI)
283-
self.underlying.deinitialize(count: 1)
284-
self.underlying.deallocate()
284+
unsafe self.underlying.deinitialize(count: 1)
285+
unsafe self.underlying.deallocate()
285286
#endif
286287
}
287288

288289

289290
@discardableResult
290291
func withLock<T>(_ body: () -> T) -> T {
291292
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
292-
os_unfair_lock_lock(self.underlying)
293+
unsafe os_unfair_lock_lock(self.underlying)
293294
#elseif os(Windows)
294295
AcquireSRWLockExclusive(self.underlying)
295296
#elseif os(WASI)
@@ -302,7 +303,7 @@ fileprivate class _Lock {
302303

303304
defer {
304305
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
305-
os_unfair_lock_unlock(self.underlying)
306+
unsafe os_unfair_lock_unlock(self.underlying)
306307
#elseif os(Windows)
307308
ReleaseSRWLockExclusive(self.underlying)
308309
#elseif os(WASI)

0 commit comments

Comments
 (0)