Skip to content

Commit 882462f

Browse files
committed
[stdlib] Array._hash(into:): Include the count as a discriminator value
This makes the hash encoding unambiguous when arrays are hashed in sequence.
1 parent 7ed7354 commit 882462f

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

stdlib/public/core/Arrays.swift.gyb

+1
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,7 @@ extension ${Self}: Hashable where Element: Hashable {
22702270

22712271
@inlinable // FIXME(sil-serialize-all)
22722272
public func _hash(into hasher: inout _Hasher) {
2273+
hasher.combine(count) // discriminator
22732274
for element in self {
22742275
hasher.combine(element)
22752276
}

validation-test/stdlib/Arrays.swift.gyb

+49-15
Original file line numberDiff line numberDiff line change
@@ -190,21 +190,55 @@ ArrayTestSuite.test("init(repeating:count:)") {
190190
}
191191

192192
ArrayTestSuite.test("Hashable") {
193-
let a1: Array<Int> = [1, 2, 3]
194-
let a2: Array<Int> = [1, 3, 2]
195-
let a3: Array<Int> = [3, 1, 2]
196-
let a4: Array<Int> = [1, 2]
197-
let a5: Array<Int> = [1]
198-
let a6: Array<Int> = []
199-
let a7: Array<Int> = [1, 1, 1]
200-
checkHashable([a1, a2, a3, a4, a5, a6, a7], equalityOracle: { $0 == $1 })
201-
202-
let aa1: Array<Array<Int>> = [[], [1], [1, 2], [2, 1]]
203-
let aa2: Array<Array<Int>> = [[], [1], [2, 1], [2, 1]]
204-
let aa3: Array<Array<Int>> = [[1], [], [2, 1], [2, 1]]
205-
let aa4: Array<Array<Int>> = [[1], [], [2, 1], [2]]
206-
let aa5: Array<Array<Int>> = [[1], [], [2, 1]]
207-
checkHashable([aa1, aa2, aa3, aa4, aa5], equalityOracle: { $0 == $1 })
193+
let a1: [Array<Int>] = [
194+
[1, 2, 3],
195+
[1, 3, 2],
196+
[3, 1, 2],
197+
[1, 2],
198+
[1],
199+
[],
200+
[1, 1, 1]
201+
]
202+
checkHashable(a1, equalityOracle: { $0 == $1 })
203+
204+
let a2: [Array<Array<Int>>] = [
205+
[[], [1], [1, 2], [2, 1]],
206+
[[], [1], [2, 1], [2, 1]],
207+
[[1], [], [2, 1], [2, 1]],
208+
[[1], [], [2, 1], [2]],
209+
[[1], [], [2, 1]]
210+
]
211+
checkHashable(a2, equalityOracle: { $0 == $1 })
212+
213+
// These arrays share the same sequence of leaf integers, but they must
214+
// still all hash differently.
215+
let a3: [Array<Array<Int>>] = [
216+
// Grouping changes must perturb the hash.
217+
[[1], [2], [3], [4], [5]],
218+
[[1, 2], [3], [4], [5]],
219+
220+
[[1], [2, 3], [4], [5]],
221+
[[1], [2], [3, 4], [5]],
222+
[[1], [2], [3], [4, 5]],
223+
224+
[[1, 2, 3], [4], [5]],
225+
[[1], [2, 3, 4], [5]],
226+
[[1], [2], [3, 4, 5]],
227+
228+
[[1, 2, 3, 4], [5]],
229+
[[1], [2, 3, 4, 5]],
230+
231+
[[1, 2], [3, 4], [5]],
232+
[[1], [2, 3], [4, 5]],
233+
[[1, 2, 3, 4, 5]],
234+
235+
// Empty arrays must perturb the hash.
236+
[[], [1], [2], [3], [4], [5]],
237+
[[1], [], [2], [3], [4], [5]],
238+
[[1], [2], [3], [4], [5], []],
239+
[[1], [], [], [2], [3], [], [4], [], [5]],
240+
]
241+
checkHashable(a3, equalityOracle: { $0 == $1 })
208242
}
209243

210244

0 commit comments

Comments
 (0)