Skip to content

Commit 48bcda3

Browse files
weissiJohannes Weiss
authored and
Johannes Weiss
committed
more Sendable conformances & Sendable Context
1 parent 3d2497e commit 48bcda3

18 files changed

+191
-29
lines changed

Sources/TSCBasic/CodableResult.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public struct CodableResult<Success, Failure>: Codable where Success: Codable, F
4949
}
5050
}
5151

52+
extension CodableResult: Sendable where Success: Sendable, Failure: Sendable {}
53+
5254
extension CodableResult where Failure == StringError {
5355
public init(body: () throws -> Success) {
5456
do {

Sources/TSCBasic/Condition.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ public struct Condition {
5050
return try body()
5151
}
5252
}
53+
54+
#if compiler(>=5.7)
55+
extension Condition: Sendable {}
56+
#endif

Sources/TSCBasic/DeltaAlgorithm.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
/// It is not an error to provide a predicate that does not satisfy these
2828
/// requirements, and the algorithm will generally produce reasonable results.
2929
/// However, it may run substantially more tests than with a good predicate.
30-
public struct DeltaAlgorithm<Change: Hashable> {
30+
public struct DeltaAlgorithm<Change: Hashable>: Sendable {
3131

3232
public init() {}
3333

Sources/TSCBasic/DiagnosticsEngine.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ extension DiagnosticData {
2121
public protocol DiagnosticLocation: Sendable, CustomStringConvertible {
2222
}
2323

24-
public struct Diagnostic: CustomStringConvertible {
24+
public struct Diagnostic: CustomStringConvertible, Sendable {
2525
/// The behavior associated with this diagnostic.
26-
public enum Behavior {
26+
public enum Behavior: Sendable {
2727
/// An error which will halt the operation.
2828
case error
2929

@@ -38,7 +38,7 @@ public struct Diagnostic: CustomStringConvertible {
3838
case ignored
3939
}
4040

41-
public struct Message {
41+
public struct Message: Sendable {
4242
/// The diagnostic's behavior.
4343
public let behavior: Behavior
4444

@@ -191,7 +191,7 @@ extension Diagnostic.Message {
191191
}
192192
}
193193

194-
public struct StringDiagnostic: DiagnosticData {
194+
public struct StringDiagnostic: DiagnosticData, Sendable {
195195
/// The diagnostic description.
196196
public let description: String
197197

Sources/TSCBasic/FileSystem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import Foundation
1313
import Dispatch
1414
import SystemPackage
1515

16-
public struct FileSystemError: Error, Equatable {
17-
public enum Kind: Equatable {
16+
public struct FileSystemError: Error, Equatable, Sendable {
17+
public enum Kind: Equatable, Sendable {
1818
/// Access to the path is denied.
1919
///
2020
/// This is used when an operation cannot be completed because a component of

Sources/TSCBasic/HashAlgorithms.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import CryptoKit
1313
#endif
1414

15-
public protocol HashAlgorithm {
15+
public protocol HashAlgorithm: Sendable {
1616

1717
/// Hashes the input bytes, returning the digest.
1818
///
@@ -31,7 +31,7 @@ extension HashAlgorithm {
3131
/// SHA-256 implementation from Secure Hash Algorithm 2 (SHA-2) set of
3232
/// cryptographic hash functions (FIPS PUB 180-2).
3333
/// Uses CryptoKit where available
34-
public struct SHA256: HashAlgorithm {
34+
public struct SHA256: HashAlgorithm, Sendable {
3535
private let underlying: HashAlgorithm
3636

3737
public init() {
@@ -197,7 +197,7 @@ struct InternalSHA256: HashAlgorithm {
197197
#if canImport(CryptoKit)
198198
@available(*, deprecated, message: "use SHA256 which abstract over platform differences")
199199
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
200-
public struct CryptoKitSHA256: HashAlgorithm {
200+
public struct CryptoKitSHA256: HashAlgorithm, Sendable {
201201
let underlying = _CryptoKitSHA256()
202202
public init() {}
203203
public func hash(_ bytes: ByteString) -> ByteString {

Sources/TSCBasic/KeyedPair.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,5 @@ public struct KeyedPair<T, K: Hashable>: Hashable {
5050
return lhs.key == rhs.key
5151
}
5252
}
53+
54+
extension KeyedPair: Sendable where T: Sendable, K: Sendable {}

Sources/TSCBasic/LazyCache.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import class Foundation.NSLock
3030
/// ```
3131
///
3232
/// See: https://bugs.swift.org/browse/SR-1042
33+
@available(*, deprecated, message: "This implementation does not work -- https://github.com/apple/swift-tools-support-core/issues/385")
3334
public struct LazyCache<Class, T> {
3435
// FIXME: It would be nice to avoid a per-instance lock, but this type isn't
3536
// intended for creating large numbers of instances of. We also really want
@@ -57,3 +58,8 @@ public struct LazyCache<Class, T> {
5758
}
5859
}
5960
}
61+
62+
#if swift(>=5.6)
63+
@available(*, unavailable) // until https://github.com/apple/swift-tools-support-core/issues/385 is fixed
64+
extension LazyCache: Sendable {}
65+
#endif

Sources/TSCBasic/OrderedDictionary.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,5 @@ extension OrderedDictionary: RandomAccessCollection {
123123
return (key, value)
124124
}
125125
}
126+
127+
extension OrderedDictionary: Sendable where Key: Sendable, Value: Sendable {}

Sources/TSCBasic/OrderedSet.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,5 @@ public func == <T>(lhs: OrderedSet<T>, rhs: OrderedSet<T>) -> Bool {
128128
}
129129

130130
extension OrderedSet: Hashable where Element: Hashable { }
131+
132+
extension OrderedSet: Sendable where Element: Sendable { }

Sources/TSCBasic/misc.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ public struct CodableRange<Bound> where Bound: Comparable & Codable {
264264
}
265265
}
266266

267+
extension CodableRange: Sendable where Bound: Sendable {}
268+
267269
extension CodableRange: Codable {
268270
private enum CodingKeys: String, CodingKey {
269271
case lowerBound, upperBound

Sources/TSCUtility/Context.swift

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,53 @@
99
*/
1010

1111
import Foundation
12+
import _Concurrency
1213

13-
/// Typealias for an any typed dictionary for arbitrary usage to store context.
14-
public typealias Context = [ObjectIdentifier: Any]
14+
public struct Context {
15+
private var backing: [ObjectIdentifier: Any] = [:]
16+
17+
@available(*, deprecated, message: "Values should be Sendable")
18+
@_disfavoredOverload
19+
public init(dictionaryLiteral keyValuePairs: (ObjectIdentifier, Any)...) {
20+
self.backing = Dictionary(uniqueKeysWithValues: keyValuePairs)
21+
}
22+
23+
public init(dictionaryLiteral keyValuePairs: (ObjectIdentifier, Sendable)...) {
24+
self.backing = Dictionary(uniqueKeysWithValues: keyValuePairs)
25+
}
26+
27+
@available(*, deprecated, message: "Values should be Sendable")
28+
@_disfavoredOverload
29+
public subscript(key: ObjectIdentifier) -> Any? {
30+
get {
31+
return self.backing[key]
32+
}
33+
set {
34+
self.backing[key] = newValue
35+
}
36+
}
37+
38+
public subscript<Value>(key: ObjectIdentifier) -> Value? where Value: Sendable {
39+
get {
40+
return self.backing[key] as? Value
41+
}
42+
set {
43+
self.backing[key] = newValue
44+
}
45+
}
46+
}
47+
48+
#if compiler(>=5.7)
49+
extension Context: /* until we can remove the support for 'Any' values */ @unchecked Sendable {}
50+
#else
51+
extension Context: UnsafeSendable {}
52+
#endif
53+
54+
@available(*, deprecated, renamed: "init()")
55+
extension Context: ExpressibleByDictionaryLiteral {
56+
public typealias Key = ObjectIdentifier
57+
public typealias Value = Any
58+
}
1559

1660
extension Context {
1761
/// Get the value for the given type.
@@ -22,16 +66,36 @@ extension Context {
2266
return value
2367
}
2468

69+
public func get<T: Sendable>(_ type: T.Type = T.self) -> T {
70+
guard let value = self.getOptional(type) else {
71+
fatalError("no type \(T.self) in context")
72+
}
73+
return value
74+
}
75+
2576
/// Get the value for the given type, if present.
77+
@available(*, deprecated, message: "Values should be Sendable")
78+
@_disfavoredOverload
2679
public func getOptional<T>(_ type: T.Type = T.self) -> T? {
2780
guard let value = self[ObjectIdentifier(T.self)] else {
2881
return nil
2982
}
3083
return value as? T
3184
}
3285

86+
/// Get the value for the given type, if present.
87+
public func getOptional<T: Sendable>(_ type: T.Type = T.self) -> T? {
88+
return self[ObjectIdentifier(T.self)]
89+
}
90+
3391
/// Set a context value for a type.
92+
@available(*, deprecated, message: "Values should be Sendable")
93+
@_disfavoredOverload
3494
public mutating func set<T>(_ value: T) {
3595
self[ObjectIdentifier(T.self)] = value
3696
}
97+
98+
public mutating func set<Value: Sendable>(_ value: Value) {
99+
self[ObjectIdentifier(Value.self)] = value
100+
}
37101
}

Sources/TSCUtility/SerializedDiagnostics.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Foundation
1111
import TSCBasic
1212

1313
/// Represents diagnostics serialized in a .dia file by the Swift compiler or Clang.
14-
public struct SerializedDiagnostics {
14+
public struct SerializedDiagnostics: Sendable {
1515
public enum Error: Swift.Error {
1616
case badMagic
1717
case unexpectedTopLevelRecord
@@ -61,7 +61,7 @@ extension SerializedDiagnostics.Error: CustomNSError {
6161
extension SerializedDiagnostics {
6262
public struct Diagnostic {
6363

64-
public enum Level: UInt64 {
64+
public enum Level: UInt64, Sendable {
6565
case ignored, note, warning, error, fatal, remark
6666
}
6767
/// The diagnostic message text.
@@ -168,7 +168,7 @@ extension SerializedDiagnostics {
168168
}
169169
}
170170

171-
public struct FixIt {
171+
public struct FixIt: Sendable {
172172
/// Start location.
173173
public var start: SourceLocation
174174
/// End location.
@@ -178,6 +178,12 @@ extension SerializedDiagnostics {
178178
}
179179
}
180180

181+
#if compiler(>=5.7)
182+
extension SerializedDiagnostics.Diagnostic: Sendable {}
183+
#else
184+
extension SerializedDiagnostics.Diagnostic: UnsafeSendable {}
185+
#endif
186+
181187
extension SerializedDiagnostics {
182188
private struct Reader: BitstreamVisitor {
183189
var diagnosticRecords: [[OwnedRecord]] = []

Sources/TSCUtility/Tracing.swift

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import Foundation
1212

13-
public enum TracingEventType: String, Codable {
13+
public enum TracingEventType: String, Codable, Sendable {
1414
case asyncBegin
1515
case asyncEnd
1616
}
@@ -51,7 +51,7 @@ public protocol TracingEventProtocol {
5151
)
5252
}
5353

54-
public protocol TracingCollectionProtocol {
54+
public protocol TracingCollectionProtocol: Sendable {
5555
var events: [TracingEventProtocol] { get set }
5656
init(_ events: [TracingEventProtocol])
5757
}
@@ -62,7 +62,7 @@ extension TracingCollectionProtocol {
6262
}
6363
}
6464

65-
public struct TracingEvent: TracingEventProtocol, Codable {
65+
public struct TracingEvent: TracingEventProtocol, Codable, Sendable {
6666
public let cat: String
6767
public let name: String
6868
public let id: String
@@ -135,13 +135,37 @@ public struct TracingEvent: TracingEventProtocol, Codable {
135135
#endif
136136
}
137137

138-
public class TracingCollection: TracingCollectionProtocol {
139-
public var events: [TracingEventProtocol] = []
138+
public final class TracingCollection {
139+
private let lock = NSLock()
140+
private var _events: [TracingEventProtocol] = []
141+
142+
public var events: [TracingEventProtocol] {
143+
get {
144+
return self.lock.withLock {
145+
self._events
146+
}
147+
}
148+
149+
set {
150+
self.lock.withLock {
151+
self._events = newValue
152+
}
153+
}
154+
}
155+
140156
public required init(_ events: [TracingEventProtocol] = []) {
141157
self.events = events
142158
}
143159
}
144160

161+
#if compiler(>=5.7)
162+
extension TracingCollection: @unchecked /* because self-locked */ Sendable {}
163+
extension TracingCollection: TracingCollectionProtocol {}
164+
#else
165+
extension TracingCollection: UnsafeSendable {}
166+
extension TracingCollection: TracingCollectionProtocol {}
167+
#endif
168+
145169
extension Context {
146170
public static func withTracing(_ collection: TracingCollectionProtocol) -> Context {
147171
return Context(dictionaryLiteral: (ObjectIdentifier(TracingCollectionProtocol.self), collection as Any))
@@ -154,10 +178,7 @@ extension Context {
154178

155179
public var tracing: TracingCollectionProtocol? {
156180
get {
157-
guard let collection = self[ObjectIdentifier(TracingCollectionProtocol.self)] as? TracingCollectionProtocol else {
158-
return nil
159-
}
160-
return collection
181+
return self[ObjectIdentifier(TracingCollectionProtocol.self)]
161182
}
162183
set {
163184
self[ObjectIdentifier(TracingCollectionProtocol.self)] = newValue

Sources/TSCUtility/Triple.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import TSCBasic
2020
/// @see Destination.target
2121
/// @see https://github.com/apple/swift-llvm/blob/stable/include/llvm/ADT/Triple.h
2222
///
23-
public struct Triple: Encodable, Equatable {
23+
public struct Triple: Encodable, Equatable, Sendable {
2424
public let tripleString: String
2525

2626
public let arch: Arch
@@ -36,7 +36,7 @@ public struct Triple: Encodable, Equatable {
3636
case unknownOS(os: String)
3737
}
3838

39-
public enum Arch: String, Encodable {
39+
public enum Arch: String, Encodable, Sendable {
4040
case x86_64
4141
case x86_64h
4242
case i686
@@ -59,12 +59,12 @@ public struct Triple: Encodable, Equatable {
5959
case mips64el
6060
}
6161

62-
public enum Vendor: String, Encodable {
62+
public enum Vendor: String, Encodable, Sendable {
6363
case unknown
6464
case apple
6565
}
6666

67-
public enum OS: String, Encodable, CaseIterable {
67+
public enum OS: String, Encodable, CaseIterable, Sendable {
6868
case darwin
6969
case macOS = "macosx"
7070
case linux
@@ -73,7 +73,7 @@ public struct Triple: Encodable, Equatable {
7373
case openbsd
7474
}
7575

76-
public enum ABI: Encodable, Equatable, RawRepresentable {
76+
public enum ABI: Encodable, Equatable, RawRepresentable, Sendable {
7777
case unknown
7878
case android
7979
case other(name: String)

Tests/TSCBasicTests/LazyCacheTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import XCTest
1313
import TSCBasic
1414

1515
class LazyCacheTests: XCTestCase {
16+
@available(*, deprecated, message: "LazyCache's implementation is broken -- https://github.com/apple/swift-tools-support-core/issues/385")
1617
func testBasics() {
1718
class Foo {
1819
var numCalls = 0

0 commit comments

Comments
 (0)