Skip to content

Commit df024d4

Browse files
committed
more Sendable conformances & Sendable Context
1 parent 539935f commit df024d4

18 files changed

+139
-34
lines changed

Sources/TSCBasic/ByteString.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import Foundation
2323
/// strings or and by eliminating wasted space in growable arrays). For
2424
/// construction of byte arrays, clients should use the `WritableByteStream` class
2525
/// and then convert to a `ByteString` when complete.
26-
public struct ByteString: ExpressibleByArrayLiteral, Hashable {
26+
public struct ByteString: ExpressibleByArrayLiteral, Hashable, Sendable {
2727
/// The buffer contents.
2828
@usableFromInline
2929
internal var _bytes: [UInt8]

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: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@
1111
import Dispatch
1212

1313
/// The payload of a diagnostic.
14-
public protocol DiagnosticData: CustomStringConvertible {
14+
public protocol DiagnosticData: CustomStringConvertible, Sendable {
1515
}
1616

1717
extension DiagnosticData {
1818
public var localizedDescription: String { self.description }
1919
}
2020

21-
public protocol DiagnosticLocation: CustomStringConvertible {
21+
public protocol DiagnosticLocation: CustomStringConvertible, Sendable {
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/FileInfo.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ public struct FileInfo: Equatable, Codable {
5858
}
5959
}
6060

61+
#if compiler(>=5.7)
62+
extension FileInfo: Sendable {}
63+
#endif
64+
6165
extension FileAttributeType: Codable {}

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,8 @@ public struct LazyCache<Class, T> {
5757
}
5858
}
5959
}
60+
61+
#if swift(>=5.6)
62+
@available(*, unavailable) // until https://github.com/apple/swift-tools-support-core/issues/385 is fixed
63+
extension LazyCache: Sendable {}
64+
#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: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,49 @@
1010

1111
import Foundation
1212

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

1657
extension Context {
1758
/// Get the value for the given type.
@@ -22,16 +63,36 @@ extension Context {
2263
return value
2364
}
2465

66+
public func get<T: Sendable>(_ type: T.Type = T.self) -> T {
67+
guard let value = self.getOptional(type) else {
68+
fatalError("no type \(T.self) in context")
69+
}
70+
return value
71+
}
72+
2573
/// Get the value for the given type, if present.
74+
@available(*, deprecated, message: "Values should be Sendable")
75+
@_disfavoredOverload
2676
public func getOptional<T>(_ type: T.Type = T.self) -> T? {
2777
guard let value = self[ObjectIdentifier(T.self)] else {
2878
return nil
2979
}
3080
return value as? T
3181
}
3282

83+
/// Get the value for the given type, if present.
84+
public func getOptional<T: Sendable>(_ type: T.Type = T.self) -> T? {
85+
return self[ObjectIdentifier(T.self)]
86+
}
87+
3388
/// Set a context value for a type.
89+
@available(*, deprecated, message: "Values should be Sendable")
90+
@_disfavoredOverload
3491
public mutating func set<T>(_ value: T) {
3592
self[ObjectIdentifier(T.self)] = value
3693
}
94+
95+
public mutating func set<Value: Sendable>(_ value: Value) {
96+
self[ObjectIdentifier(Value.self)] = value
97+
}
3798
}

Sources/TSCUtility/PolymorphicCodable.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public struct PolymorphicCodable<T: PolymorphicCodableProtocol>: Codable {
4242
}
4343
}
4444

45+
extension PolymorphicCodable: Sendable where T: Sendable {}
46+
4547
@propertyWrapper
4648
public struct PolymorphicCodableArray<T: PolymorphicCodableProtocol>: Codable {
4749
public let value: [PolymorphicCodable<T>]
@@ -54,3 +56,5 @@ public struct PolymorphicCodableArray<T: PolymorphicCodableProtocol>: Codable {
5456
return value.map{ $0.value }
5557
}
5658
}
59+
60+
extension PolymorphicCodableArray: Sendable where T: Sendable {}

Sources/TSCUtility/SerializedDiagnostics.swift

Lines changed: 5 additions & 5 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
@@ -59,9 +59,9 @@ extension SerializedDiagnostics.Error: CustomNSError {
5959
}
6060

6161
extension SerializedDiagnostics {
62-
public struct Diagnostic {
62+
public struct Diagnostic: Sendable {
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.
@@ -149,7 +149,7 @@ extension SerializedDiagnostics {
149149
}
150150
}
151151

152-
public struct SourceLocation: Equatable {
152+
public struct SourceLocation: Equatable, Sendable {
153153
/// The filename associated with the diagnostic.
154154
public var filename: String
155155
public var line: UInt64
@@ -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.

Sources/TSCUtility/Tracing.swift

Lines changed: 26 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,33 @@ public struct TracingEvent: TracingEventProtocol, Codable {
135135
#endif
136136
}
137137

138-
public class TracingCollection: TracingCollectionProtocol {
139-
public var events: [TracingEventProtocol] = []
138+
public final class TracingCollection: TracingCollectionProtocol {
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+
#endif
164+
145165
extension Context {
146166
public static func withTracing(_ collection: TracingCollectionProtocol) -> Context {
147167
return Context(dictionaryLiteral: (ObjectIdentifier(TracingCollectionProtocol.self), collection as Any))
@@ -154,10 +174,7 @@ extension Context {
154174

155175
public var tracing: TracingCollectionProtocol? {
156176
get {
157-
guard let collection = self[ObjectIdentifier(TracingCollectionProtocol.self)] as? TracingCollectionProtocol else {
158-
return nil
159-
}
160-
return collection
177+
return self[ObjectIdentifier(TracingCollectionProtocol.self)]
161178
}
162179
set {
163180
self[ObjectIdentifier(TracingCollectionProtocol.self)] = newValue

0 commit comments

Comments
 (0)