File tree Expand file tree Collapse file tree 4 files changed +67
-0
lines changed Expand file tree Collapse file tree 4 files changed +67
-0
lines changed Original file line number Diff line number Diff line change @@ -35,6 +35,7 @@ This library comes with a number of tools that make working with Swift concurren
3535testable.
3636
3737 * [ ` LockIsolated ` ] ( #lockisolated )
38+ * [ ` AnyHashableSendable ` ] ( #anyhashablesendable )
3839 * [ Streams] ( #streams )
3940 * [ Tasks] ( #tasks )
4041 * [ Serial execution] ( #serial-execution )
@@ -44,6 +45,11 @@ testable.
4445The ` LockIsolated ` type helps wrap other values in an isolated context. It wraps the value in a
4546class with a lock, which allows you to read and write the value with a synchronous interface.
4647
48+ ### ` AnyHashableSendable `
49+
50+ The ` AnyHashableSendable ` type is a type-erased wrapper like ` AnyHashable ` that preserves the
51+ sendability of the underlying value.
52+
4753### Streams
4854
4955The library comes with numerous helper APIs spread across the two Swift stream types:
Original file line number Diff line number Diff line change 1+ /// A type-erased hashable, sendable value.
2+ ///
3+ /// A sendable version of `AnyHashable` that is useful in working around the limitation that an
4+ /// existential `any Hashable` does not conform to `Hashable`.
5+ public struct AnyHashableSendable : Hashable , Sendable {
6+ public let base : any Hashable & Sendable
7+
8+ /// Creates a type-erased hashable, sendable value that wraps the given instance.
9+ public init ( _ base: some Hashable & Sendable ) {
10+ if let base = base as? AnyHashableSendable {
11+ self = base
12+ } else {
13+ self . base = base
14+ }
15+ }
16+
17+ public static func == ( lhs: Self , rhs: Self ) -> Bool {
18+ AnyHashable ( lhs. base) == AnyHashable ( rhs. base)
19+ }
20+
21+ public func hash( into hasher: inout Hasher ) {
22+ hasher. combine ( base)
23+ }
24+ }
25+
26+ extension AnyHashableSendable : CustomDebugStringConvertible {
27+ public var debugDescription : String {
28+ " AnyHashableSendable( " + String( reflecting: base) + " ) "
29+ }
30+ }
31+
32+ extension AnyHashableSendable : CustomReflectable {
33+ public var customMirror : Mirror {
34+ Mirror ( self , children: [ " value " : base] )
35+ }
36+ }
37+
38+ extension AnyHashableSendable : CustomStringConvertible {
39+ public var description : String {
40+ String ( describing: base)
41+ }
42+ }
Original file line number Diff line number Diff line change @@ -236,6 +236,7 @@ need to make weaker assertions due to non-determinism, but can still assert on s
236236### Data races
237237
238238- `` LockIsolated ``
239+ - `` AnyHashableSendable ``
239240
240241### Serial execution
241242
Original file line number Diff line number Diff line change 1+ import ConcurrencyExtras
2+ import XCTest
3+
4+ final class AnyHashableSendableTests : XCTestCase {
5+ func testBasics( ) {
6+ XCTAssertEqual ( AnyHashableSendable ( 1 ) , AnyHashableSendable ( 1 ) )
7+ XCTAssertNotEqual ( AnyHashableSendable ( 1 ) , AnyHashableSendable ( 2 ) )
8+
9+ func make( _ base: some Hashable & Sendable ) -> AnyHashableSendable {
10+ AnyHashableSendable ( base)
11+ }
12+
13+ let flat = make ( 1 )
14+ let nested = make ( flat)
15+
16+ XCTAssertEqual ( flat, nested)
17+ }
18+ }
You can’t perform that action at this time.
0 commit comments