Skip to content

Commit bba2979

Browse files
committed
more Sendable conformances & Sendable Context
1 parent f0e80d1 commit bba2979

18 files changed

+314
-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: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,117 @@
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+
15+
public struct Context {
16+
private var backing: [ObjectIdentifier: Any] = [:]
17+
18+
#if compiler(>=5.5.2)
19+
@available(*, deprecated, message: "Values should be Sendable")
20+
@_disfavoredOverload
21+
public init(dictionaryLiteral keyValuePairs: (ObjectIdentifier, Any)...) {
22+
self.backing = Dictionary(uniqueKeysWithValues: keyValuePairs)
23+
}
24+
25+
public init(dictionaryLiteral keyValuePairs: (ObjectIdentifier, Sendable)...) {
26+
self.backing = Dictionary(uniqueKeysWithValues: keyValuePairs)
27+
}
28+
29+
@available(*, deprecated, message: "Values should be Sendable")
30+
@_disfavoredOverload
31+
public subscript(key: ObjectIdentifier) -> Any? {
32+
get {
33+
return self.backing[key]
34+
}
35+
set {
36+
self.backing[key] = newValue
37+
}
38+
}
39+
40+
public subscript<Value>(key: ObjectIdentifier) -> Value? where Value: Sendable {
41+
get {
42+
return self.backing[key] as? Value
43+
}
44+
set {
45+
self.backing[key] = newValue
46+
}
47+
}
48+
#else
49+
public init(dictionaryLiteral keyValuePairs: (ObjectIdentifier, Any)...) {
50+
self.backing = Dictionary(uniqueKeysWithValues: keyValuePairs)
51+
}
52+
53+
public subscript(key: ObjectIdentifier) -> Any? {
54+
get {
55+
return self.backing[key]
56+
}
57+
set {
58+
self.backing[key] = newValue
59+
}
60+
}
61+
#endif
62+
}
63+
64+
#if compiler(>=5.7)
65+
extension Context: /* until we can remove the support for 'Any' values */ @unchecked Sendable {}
66+
#else
67+
#if compiler(>=5.5.2)
68+
extension Context: UnsafeSendable {}
69+
#endif
70+
#endif
71+
72+
@available(*, deprecated, renamed: "init()")
73+
extension Context: ExpressibleByDictionaryLiteral {
74+
public typealias Key = ObjectIdentifier
75+
public typealias Value = Any
76+
}
1577

1678
extension Context {
79+
#if compiler(>=5.5.2)
80+
/// Get the value for the given type.
81+
@available(*, deprecated, message: "Values should be Sendable")
82+
@_disfavoredOverload
83+
public func get<T>(_ type: T.Type = T.self) -> T {
84+
guard let value = getOptional(type) else {
85+
fatalError("no type \(T.self) in context")
86+
}
87+
return value
88+
}
89+
90+
public func get<T: Sendable>(_ type: T.Type = T.self) -> T {
91+
guard let value = self.getOptional(type) else {
92+
fatalError("no type \(T.self) in context")
93+
}
94+
return value
95+
}
96+
97+
/// Get the value for the given type, if present.
98+
@available(*, deprecated, message: "Values should be Sendable")
99+
@_disfavoredOverload
100+
public func getOptional<T>(_ type: T.Type = T.self) -> T? {
101+
guard let value = self[ObjectIdentifier(T.self)] else {
102+
return nil
103+
}
104+
return value as? T
105+
}
106+
107+
/// Get the value for the given type, if present.
108+
public func getOptional<T: Sendable>(_ type: T.Type = T.self) -> T? {
109+
return self[ObjectIdentifier(T.self)]
110+
}
111+
112+
/// Set a context value for a type.
113+
@available(*, deprecated, message: "Values should be Sendable")
114+
@_disfavoredOverload
115+
public mutating func set<T>(_ value: T) {
116+
self[ObjectIdentifier(T.self)] = value
117+
}
118+
119+
public mutating func set<Value: Sendable>(_ value: Value) {
120+
self[ObjectIdentifier(Value.self)] = value
121+
}
122+
#else
17123
/// Get the value for the given type.
18124
public func get<T>(_ type: T.Type = T.self) -> T {
19125
guard let value = getOptional(type) else {
@@ -34,4 +140,5 @@ extension Context {
34140
public mutating func set<T>(_ value: T) {
35141
self[ObjectIdentifier(T.self)] = value
36142
}
143+
#endif
37144
}

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]] = []

0 commit comments

Comments
 (0)