Skip to content

Commit 5ab6711

Browse files
committed
[test] MinimalHashable types: Replace hashValue hook with hash(into:)
1 parent 8d18d1a commit 5ab6711

File tree

6 files changed

+83
-59
lines changed

6 files changed

+83
-59
lines changed

stdlib/private/StdlibUnittest/MinimalTypes.swift

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ public struct MinimalComparableValue : Equatable, Comparable {
111111
/// other conformances.
112112
public struct MinimalHashableValue : Equatable, Hashable {
113113
public static var timesEqualEqualWasCalled: Int = 0
114-
public static var timesHashValueWasCalled: Int = 0
114+
public static var timesHashIntoWasCalled: Int = 0
115115

116116
public static var equalImpl =
117117
ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
118-
public static var hashValueImpl =
119-
ResettableValue<(Int) -> Int>({ $0.hashValue })
118+
public static var hashIntoImpl =
119+
ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
120120

121121
public var value: Int
122122
public var identity: Int
@@ -140,8 +140,14 @@ public struct MinimalHashableValue : Equatable, Hashable {
140140
}
141141

142142
public var hashValue: Int {
143-
MinimalHashableValue.timesHashValueWasCalled += 1
144-
return MinimalHashableValue.hashValueImpl.value(value)
143+
var hasher = _Hasher()
144+
hasher.combine(self)
145+
return hasher.finalize()
146+
}
147+
148+
public func _hash(into hasher: inout _Hasher) {
149+
MinimalHashableValue.timesHashIntoWasCalled += 1
150+
MinimalHashableValue.hashIntoImpl.value(value, &hasher)
145151
}
146152
}
147153

@@ -158,12 +164,12 @@ extension MinimalHashableValue: CustomStringConvertible {
158164
/// other conformances.
159165
public class MinimalHashableClass : Equatable, Hashable {
160166
public static var timesEqualEqualWasCalled: Int = 0
161-
public static var timesHashValueWasCalled: Int = 0
167+
public static var timesHashIntoWasCalled: Int = 0
162168

163169
public static var equalImpl =
164170
ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
165-
public static var hashValueImpl =
166-
ResettableValue<(Int) -> Int>({ $0.hashValue })
171+
public static var hashIntoImpl =
172+
ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
167173

168174
public var value: Int
169175
public var identity: Int
@@ -187,8 +193,14 @@ public class MinimalHashableClass : Equatable, Hashable {
187193
}
188194

189195
public var hashValue: Int {
190-
MinimalHashableClass.timesHashValueWasCalled += 1
191-
return MinimalHashableClass.hashValueImpl.value(value)
196+
var hasher = _Hasher()
197+
hasher.combine(self)
198+
return hasher.finalize()
199+
}
200+
201+
public func _hash(into hasher: inout _Hasher) {
202+
MinimalHashableClass.timesHashIntoWasCalled += 1
203+
MinimalHashableClass.hashIntoImpl.value(value, &hasher)
192204
}
193205
}
194206

@@ -201,15 +213,15 @@ extension MinimalHashableClass: CustomStringConvertible {
201213

202214

203215
public var GenericMinimalHashableValue_timesEqualEqualWasCalled: Int = 0
204-
public var GenericMinimalHashableValue_timesHashValueWasCalled: Int = 0
216+
public var GenericMinimalHashableValue_timesHashIntoWasCalled: Int = 0
205217

206218
public var GenericMinimalHashableValue_equalImpl =
207219
ResettableValue<(Any, Any) -> Bool>({ _, _ in
208220
fatalError("GenericMinimalHashableValue_equalImpl is not set yet")
209221
})
210-
public var GenericMinimalHashableValue_hashValueImpl =
211-
ResettableValue<(Any) -> Int>({ _ in
212-
fatalError("GenericMinimalHashableValue_hashValueImpl is not set yet")
222+
public var GenericMinimalHashableValue_hashIntoImpl =
223+
ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
224+
fatalError("GenericMinimalHashableValue_hashIntoImpl is not set yet")
213225
})
214226

215227
/// A type that conforms only to `Equatable` and `Hashable`.
@@ -239,8 +251,14 @@ public struct GenericMinimalHashableValue<Wrapped> : Equatable, Hashable {
239251
}
240252

241253
public var hashValue: Int {
242-
GenericMinimalHashableValue_timesHashValueWasCalled += 1
243-
return GenericMinimalHashableValue_hashValueImpl.value(value)
254+
var hasher = _Hasher()
255+
hasher.combine(self)
256+
return hasher.finalize()
257+
}
258+
259+
public func _hash(into hasher: inout _Hasher) {
260+
GenericMinimalHashableValue_timesHashIntoWasCalled += 1
261+
GenericMinimalHashableValue_hashIntoImpl.value(value, &hasher)
244262
}
245263
}
246264

@@ -251,15 +269,15 @@ extension GenericMinimalHashableValue: CustomStringConvertible {
251269
}
252270

253271
public var GenericMinimalHashableClass_timesEqualEqualWasCalled: Int = 0
254-
public var GenericMinimalHashableClass_timesHashValueWasCalled: Int = 0
272+
public var GenericMinimalHashableClass_timesHashIntoWasCalled: Int = 0
255273

256274
public var GenericMinimalHashableClass_equalImpl =
257275
ResettableValue<(Any, Any) -> Bool>({ _, _ in
258276
fatalError("GenericMinimalHashableClass_equalImpl is not set yet")
259277
})
260-
public var GenericMinimalHashableClass_hashValueImpl =
261-
ResettableValue<(Any) -> Int>({ _ in
262-
fatalError("GenericMinimalHashableClass_hashValueImpl is not set yet")
278+
public var GenericMinimalHashableClass_hashIntoImpl =
279+
ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
280+
fatalError("GenericMinimalHashableClass_hashIntoImpl is not set yet")
263281
})
264282

265283
/// A type that conforms only to `Equatable` and `Hashable`.
@@ -289,8 +307,14 @@ public class GenericMinimalHashableClass<Wrapped> : Equatable, Hashable {
289307
}
290308

291309
public var hashValue: Int {
292-
GenericMinimalHashableClass_timesHashValueWasCalled += 1
293-
return GenericMinimalHashableClass_hashValueImpl.value(value)
310+
var hasher = _Hasher()
311+
hasher.combine(self)
312+
return hasher.finalize()
313+
}
314+
315+
public func _hash(into hasher: inout _Hasher) {
316+
GenericMinimalHashableClass_timesHashIntoWasCalled += 1
317+
GenericMinimalHashableClass_hashIntoImpl.value(value, &hasher)
294318
}
295319
}
296320

validation-test/stdlib/AnyHashable.swift.gyb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import Foundation
5858
let AnyHashableTests = TestSuite("AnyHashableTests")
5959

6060
AnyHashableTests.test("CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable") {
61-
var v = AnyHashable(CustomPrintableValue(1))
61+
let v = AnyHashable(CustomPrintableValue(1))
6262
expectPrinted("(value: 1).description", v)
6363
expectDebugPrinted("AnyHashable((value: 1).debugDescription)", v)
6464
expectDumped(
@@ -117,8 +117,8 @@ AnyHashableTests.test("AnyHashable(${wrapped}<OpaqueValue<Int>>)/Hashable") {
117117
${wrapped}_equalImpl.value = {
118118
($0 as! ${payload}).value == ($1 as! ${payload}).value
119119
}
120-
${wrapped}_hashValueImpl.value = {
121-
($0 as! ${payload}).value
120+
${wrapped}_hashIntoImpl.value = {
121+
$1.combine(($0 as! ${payload}).value)
122122
}
123123
let xs = (0...5).flatMap {
124124
[ ${wrapped}(${payload}($0), identity: 0),
@@ -142,7 +142,7 @@ AnyHashableTests.test("AnyHashable(mixed minimal hashables)/Hashable") {
142142
var xs: [AnyHashable] = []
143143

144144
% for wrapped in ['MinimalHashableValue', 'MinimalHashableClass']:
145-
xs += (0...5).flatMap {
145+
xs += (0..<6).flatMap {
146146
[ ${wrapped}($0, identity: 0),
147147
${wrapped}($0, identity: 1) ].map(AnyHashable.init)
148148
}
@@ -157,18 +157,18 @@ AnyHashableTests.test("AnyHashable(mixed minimal hashables)/Hashable") {
157157
}
158158
return (lhs as! LifetimeTracked) == (rhs as! LifetimeTracked)
159159
}
160-
${wrapped}_hashValueImpl.value = {
161-
payload in
160+
${wrapped}_hashIntoImpl.value = { payload, hasher in
162161
if let x = payload as? OpaqueValue<Int> {
163-
return x.value
162+
hasher.combine(x.value)
163+
return
164164
}
165-
return (payload as! LifetimeTracked).value
165+
hasher.combine((payload as! LifetimeTracked).value)
166166
}
167167
% end
168168

169169
% for wrapped in ['GenericMinimalHashableValue', 'GenericMinimalHashableClass']:
170170
% for payload in [ 'OpaqueValue<Int>', 'LifetimeTracked' ]:
171-
xs += (0...5).flatMap {
171+
xs += (0..<6).flatMap {
172172
[ ${wrapped}(${payload}($0), identity: 0),
173173
${wrapped}(${payload}($0), identity: 1) ].map(AnyHashable.init)
174174
}
@@ -311,8 +311,8 @@ AnyHashableTests.test("AnyHashable(${genericWrapped}<${payload}>)/Hashable") {
311311
GenericMinimalHashableValue_equalImpl.value = {
312312
($0 as! ${payload}).value == ($1 as! ${payload}).value
313313
}
314-
GenericMinimalHashableValue_hashValueImpl.value = {
315-
($0 as! ${payload}).value
314+
GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
315+
hasher.combine((v as! ${payload}).value)
316316
}
317317
let xs = (-2...2).flatMap {
318318
[ ${genericWrapped}(
@@ -379,8 +379,8 @@ AnyHashableTests.test("AnyHashable containing values with recursive custom repre
379379
GenericMinimalHashableValue_equalImpl.value = {
380380
($0 as! ${payload}).value == ($1 as! ${payload}).value
381381
}
382-
GenericMinimalHashableValue_hashValueImpl.value = {
383-
($0 as! ${payload}).value
382+
GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
383+
hasher.combine((v as! ${payload}).value)
384384
}
385385
// If the custom representation has its own custom representation,
386386
// we ignore it.

validation-test/stdlib/CollectionType.swift.gyb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ CollectionTypeTests.test("Set<T>.find/CustomImplementation/${dispatch}") {
659659
let s = Set<MinimalHashableValue>(
660660
test.sequence.map { MinimalHashableValue($0.value) })
661661
MinimalHashableValue.timesEqualEqualWasCalled = 0
662-
MinimalHashableValue.timesHashValueWasCalled = 0
662+
MinimalHashableValue.timesHashIntoWasCalled = 0
663663
expectEqual(
664664
test.expected
665665
.map { _ in MinimalHashableValue(test.element.value) },
@@ -671,11 +671,11 @@ CollectionTypeTests.test("Set<T>.find/CustomImplementation/${dispatch}") {
671671
0, MinimalHashableValue.timesEqualEqualWasCalled,
672672
stackTrace: SourceLocStack().with(test.loc))
673673
expectEqual(
674-
0, MinimalHashableValue.timesHashValueWasCalled,
674+
0, MinimalHashableValue.timesHashIntoWasCalled,
675675
stackTrace: SourceLocStack().with(test.loc))
676676
} else {
677677
expectNotEqual(
678-
0, MinimalHashableValue.timesHashValueWasCalled,
678+
0, MinimalHashableValue.timesHashIntoWasCalled,
679679
stackTrace: SourceLocStack().with(test.loc))
680680
}
681681
if test.expected != nil {

validation-test/stdlib/Dictionary.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,13 @@ DictionaryTestSuite.test("COW.Fast.SubscriptWithKeyDoesNotReallocate")
274274
do {
275275
var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
276276
MinimalHashableValue.timesEqualEqualWasCalled = 0
277-
MinimalHashableValue.timesHashValueWasCalled = 0
277+
MinimalHashableValue.timesHashIntoWasCalled = 0
278278
expectNil(d2[MinimalHashableValue(42)])
279279

280280
// If the dictionary is empty, we shouldn't be computing the hash value of
281281
// the provided key.
282282
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
283-
expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
283+
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
284284
}
285285
}
286286

@@ -330,14 +330,14 @@ DictionaryTestSuite.test("COW.Slow.SubscriptWithKeyDoesNotReallocate")
330330
do {
331331
var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
332332
MinimalHashableClass.timesEqualEqualWasCalled = 0
333-
MinimalHashableClass.timesHashValueWasCalled = 0
333+
MinimalHashableClass.timesHashIntoWasCalled = 0
334334

335335
expectNil(d2[MinimalHashableClass(42)])
336336

337337
// If the dictionary is empty, we shouldn't be computing the hash value of
338338
// the provided key.
339339
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
340-
expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
340+
expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
341341
}
342342
}
343343

@@ -864,13 +864,13 @@ DictionaryTestSuite.test("COW.Fast.IndexForKeyDoesNotReallocate") {
864864
do {
865865
var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
866866
MinimalHashableValue.timesEqualEqualWasCalled = 0
867-
MinimalHashableValue.timesHashValueWasCalled = 0
867+
MinimalHashableValue.timesHashIntoWasCalled = 0
868868
expectNil(d2.index(forKey: MinimalHashableValue(42)))
869869

870870
// If the dictionary is empty, we shouldn't be computing the hash value of
871871
// the provided key.
872872
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
873-
expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
873+
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
874874
}
875875
}
876876

@@ -901,13 +901,13 @@ DictionaryTestSuite.test("COW.Slow.IndexForKeyDoesNotReallocate") {
901901
do {
902902
var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
903903
MinimalHashableClass.timesEqualEqualWasCalled = 0
904-
MinimalHashableClass.timesHashValueWasCalled = 0
904+
MinimalHashableClass.timesHashIntoWasCalled = 0
905905
expectNil(d2.index(forKey: MinimalHashableClass(42)))
906906

907907
// If the dictionary is empty, we shouldn't be computing the hash value of
908908
// the provided key.
909909
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
910-
expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
910+
expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
911911
}
912912
}
913913

@@ -1713,13 +1713,13 @@ DictionaryTestSuite.test("mapValues(_:)") {
17131713
uniqueKeysWithValues: d1.lazy.map { (MinimalHashableValue($0), $1) })
17141714
expectEqual(d3.count, 3)
17151715
MinimalHashableValue.timesEqualEqualWasCalled = 0
1716-
MinimalHashableValue.timesHashValueWasCalled = 0
1716+
MinimalHashableValue.timesHashIntoWasCalled = 0
17171717

17181718
// Calling mapValues shouldn't ever recalculate any hashes.
17191719
let d4 = d3.mapValues(String.init)
17201720
expectEqual(d4.count, d3.count)
17211721
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
1722-
expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
1722+
expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
17231723
}
17241724
}
17251725

validation-test/stdlib/SequenceType.swift.gyb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ SequenceTypeTests.test("Set<T>.contains/CustomImplementation/${dispatch}") {
573573
let s = Set<MinimalHashableValue>(
574574
test.sequence.map { MinimalHashableValue($0.value) })
575575
MinimalHashableValue.timesEqualEqualWasCalled = 0
576-
MinimalHashableValue.timesHashValueWasCalled = 0
576+
MinimalHashableValue.timesHashIntoWasCalled = 0
577577
expectEqual(
578578
test.expected != nil,
579579
call${dispatch}Contains(s, MinimalHashableValue(test.element.value)),
@@ -583,11 +583,11 @@ SequenceTypeTests.test("Set<T>.contains/CustomImplementation/${dispatch}") {
583583
0, MinimalHashableValue.timesEqualEqualWasCalled,
584584
stackTrace: SourceLocStack().with(test.loc))
585585
expectEqual(
586-
0, MinimalHashableValue.timesHashValueWasCalled,
586+
0, MinimalHashableValue.timesHashIntoWasCalled,
587587
stackTrace: SourceLocStack().with(test.loc))
588588
} else {
589589
expectNotEqual(
590-
0, MinimalHashableValue.timesHashValueWasCalled,
590+
0, MinimalHashableValue.timesHashIntoWasCalled,
591591
stackTrace: SourceLocStack().with(test.loc))
592592
}
593593
if test.expected != nil {

0 commit comments

Comments
 (0)