Skip to content

Commit 97ec296

Browse files
committed
[SE-0206][stdlib] Hasher, SipHash: Make non-public declarations internal
Newly internal declarations include Hasher._seed and the integer overloads of Hasher._combine(_:), as well as _SipHash13 and _SipHash24. Unify the interfaces of these SipHash testing structs with Hasher. Update SipHash test to cover Hasher, too. Add @usableFromInline to all newly internal stuff. In addition to its normal use, it also enables white box testing; compile tests that need to use these declarations with -disable-access-control.
1 parent 641d9b1 commit 97ec296

File tree

5 files changed

+107
-80
lines changed

5 files changed

+107
-80
lines changed

stdlib/public/core/Hasher.swift

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,18 @@ public struct Hasher {
275275
/// This is not recommended for production use, but it is useful in certain
276276
/// test environments where randomization may lead to unwanted nondeterminism
277277
/// of test results.
278-
public // SPI
279-
static var _isDeterministic: Bool {
280-
@inlinable
278+
@inlinable
279+
internal static var _isDeterministic: Bool {
281280
@inline(__always)
282281
get {
283-
return _swift_stdlib_Hashing_parameters.deterministic;
282+
return _swift_stdlib_Hashing_parameters.deterministic
284283
}
285284
}
286285

287286
/// The 128-bit hash seed used to initialize the hasher state. Initialized
288287
/// once during process startup.
289-
public // SPI
290-
static var _seed: (UInt64, UInt64) {
291-
@inlinable
288+
@inlinable
289+
internal static var _seed: (UInt64, UInt64) {
292290
@inline(__always)
293291
get {
294292
// The seed itself is defined in C++ code so that it is initialized during
@@ -309,39 +307,39 @@ public struct Hasher {
309307
value._hash(into: &self)
310308
}
311309

312-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
313310
@effects(releasenone)
314-
public mutating func _combine(_ value: UInt) {
311+
@usableFromInline
312+
internal mutating func _combine(_ value: UInt) {
315313
_core.combine(value)
316314
}
317315

318-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
319316
@effects(releasenone)
320-
public mutating func _combine(_ value: UInt64) {
317+
@usableFromInline
318+
internal mutating func _combine(_ value: UInt64) {
321319
_core.combine(value)
322320
}
323321

324-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
325322
@effects(releasenone)
326-
public mutating func _combine(_ value: UInt32) {
323+
@usableFromInline
324+
internal mutating func _combine(_ value: UInt32) {
327325
_core.combine(value)
328326
}
329327

330-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
331328
@effects(releasenone)
332-
public mutating func _combine(_ value: UInt16) {
329+
@usableFromInline
330+
internal mutating func _combine(_ value: UInt16) {
333331
_core.combine(value)
334332
}
335333

336-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
337334
@effects(releasenone)
338-
public mutating func _combine(_ value: UInt8) {
335+
@usableFromInline
336+
internal mutating func _combine(_ value: UInt8) {
339337
_core.combine(value)
340338
}
341339

342-
//FIXME: Convert to @usableFromInline internal once integers hash correctly.
343340
@effects(releasenone)
344-
public mutating func _combine(bytes value: UInt64, count: Int) {
341+
@usableFromInline
342+
internal mutating func _combine(bytes value: UInt64, count: Int) {
345343
_core.combine(bytes: value, count: count)
346344
}
347345

stdlib/public/core/SipHash.swift

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,46 +118,72 @@ internal struct _SipHash24Core: _HasherCore {
118118
}
119119
}
120120

121-
// FIXME: This type only exists to facilitate testing.
122-
public // @testable
123-
struct _SipHash13 {
121+
// FIXME: This type only exists to facilitate testing, and should not exist in
122+
// production builds.
123+
@usableFromInline // @testable
124+
internal struct _SipHash13 {
124125
internal typealias Core = _BufferingHasher<_SipHash13Core>
125126

126127
internal var _core: Core
127128

128-
public init(seed: (UInt64, UInt64)) { _core = Core(seed: seed) }
129-
public mutating func _combine(_ v: UInt) { _core.combine(v) }
130-
public mutating func _combine(_ v: UInt64) { _core.combine(v) }
131-
public mutating func _combine(_ v: UInt32) { _core.combine(v) }
132-
public mutating func _combine(_ v: UInt16) { _core.combine(v) }
133-
public mutating func _combine(_ v: UInt8) { _core.combine(v) }
134-
public mutating func combine(bytes v: UInt64, count: Int) {
129+
@usableFromInline // @testable
130+
internal init(_seed: (UInt64, UInt64)) { _core = Core(seed: _seed) }
131+
@usableFromInline // @testable
132+
internal mutating func _combine(_ v: UInt) { _core.combine(v) }
133+
@usableFromInline // @testable
134+
internal mutating func _combine(_ v: UInt64) { _core.combine(v) }
135+
@usableFromInline // @testable
136+
internal mutating func _combine(_ v: UInt32) { _core.combine(v) }
137+
@usableFromInline // @testable
138+
internal mutating func _combine(_ v: UInt16) { _core.combine(v) }
139+
@usableFromInline // @testable
140+
internal mutating func _combine(_ v: UInt8) { _core.combine(v) }
141+
@usableFromInline // @testable
142+
internal mutating func _combine(bytes v: UInt64, count: Int) {
135143
_core.combine(bytes: v, count: count)
136144
}
137-
public mutating func combine(bytes: UnsafeRawBufferPointer) {
145+
@usableFromInline // @testable
146+
internal mutating func combine(bytes: UnsafeRawBufferPointer) {
138147
_core.combine(bytes: bytes)
139148
}
140-
public mutating func finalize() -> UInt64 { return _core.finalize() }
149+
@usableFromInline // @testable
150+
internal __consuming func finalize() -> UInt64 {
151+
var core = _core
152+
return core.finalize()
153+
}
141154
}
142155

143-
// FIXME: This type only exists to facilitate testing.
144-
public // @testable
145-
struct _SipHash24 {
156+
// FIXME: This type only exists to facilitate testing, and should not exist in
157+
// production builds.
158+
@usableFromInline // @testable
159+
internal struct _SipHash24 {
146160
internal typealias Core = _BufferingHasher<_SipHash24Core>
147161

148162
internal var _core: Core
149163

150-
public init(seed: (UInt64, UInt64)) { _core = Core(seed: seed) }
151-
public mutating func _combine(_ v: UInt) { _core.combine(v) }
152-
public mutating func _combine(_ v: UInt64) { _core.combine(v) }
153-
public mutating func _combine(_ v: UInt32) { _core.combine(v) }
154-
public mutating func _combine(_ v: UInt16) { _core.combine(v) }
155-
public mutating func _combine(_ v: UInt8) { _core.combine(v) }
156-
public mutating func combine(bytes v: UInt64, count: Int) {
164+
@usableFromInline // @testable
165+
internal init(_seed: (UInt64, UInt64)) { _core = Core(seed: _seed) }
166+
@usableFromInline // @testable
167+
internal mutating func _combine(_ v: UInt) { _core.combine(v) }
168+
@usableFromInline // @testable
169+
internal mutating func _combine(_ v: UInt64) { _core.combine(v) }
170+
@usableFromInline // @testable
171+
internal mutating func _combine(_ v: UInt32) { _core.combine(v) }
172+
@usableFromInline // @testable
173+
internal mutating func _combine(_ v: UInt16) { _core.combine(v) }
174+
@usableFromInline // @testable
175+
internal mutating func _combine(_ v: UInt8) { _core.combine(v) }
176+
@usableFromInline // @testable
177+
internal mutating func _combine(bytes v: UInt64, count: Int) {
157178
_core.combine(bytes: v, count: count)
158179
}
159-
public mutating func combine(bytes: UnsafeRawBufferPointer) {
180+
@usableFromInline // @testable
181+
internal mutating func combine(bytes: UnsafeRawBufferPointer) {
160182
_core.combine(bytes: bytes)
161183
}
162-
public mutating func finalize() -> UInt64 { return _core.finalize() }
184+
@usableFromInline // @testable
185+
internal __consuming func finalize() -> UInt64 {
186+
var core = _core
187+
return core.finalize()
188+
}
163189
}

validation-test/stdlib/FixedPoint.swift.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swiftgyb
1+
// RUN: %target-run-stdlib-swiftgyb
22
// REQUIRES: executable_test
33

44
import StdlibUnittest
@@ -242,7 +242,7 @@ FixedPoint.test("${Self}.hashValue") {
242242
let input = get${Self}(${input})
243243
let output = getInt(input.hashValue)
244244

245-
var hasher = _SipHash13(seed: Hasher._seed)
245+
var hasher = _SipHash13(_seed: Hasher._seed)
246246
% if prepare_bit_pattern(input, word_bits, self_ty.is_signed) == input:
247247
hasher._combine(UInt(truncatingIfNeeded: ${input} as ${"" if self_ty.is_signed else "U"}Int))
248248
% else:

validation-test/stdlib/HashingRandomization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -module-name main %s -o %t/hash
2+
// RUN: %target-build-swift -Xfrontend -disable-access-control -module-name main %s -o %t/hash
33
// RUN: (export -n %env-SWIFT_DETERMINISTIC_HASHING; %target-run %t/hash && %target-run %t/hash) | %FileCheck --check-prefixes=RANDOM %s
44
// RUN: (export %env-SWIFT_DETERMINISTIC_HASHING=1; %target-run %t/hash && %target-run %t/hash) | %FileCheck --check-prefixes=STABLE %s
55

validation-test/stdlib/SipHash.swift

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
// RUN: %target-run-simple-swiftgyb
1+
// RUN: %target-run-stdlib-swiftgyb
22
// REQUIRES: executable_test
33

44
import StdlibUnittest
55

66
let SipHashTests = TestSuite("SipHashTests")
77

8+
extension Hasher {
9+
typealias HashValue = Int
10+
}
11+
extension _SipHash13 {
12+
typealias HashValue = UInt64
13+
}
14+
extension _SipHash24 {
15+
typealias HashValue = UInt64
16+
}
17+
818
struct SipHashTest {
919
let input: [UInt8]
1020
let seed: (UInt64, UInt64)
@@ -228,23 +238,24 @@ struct Loop<C: Collection>: Sequence, IteratorProtocol {
228238
}
229239

230240
% for (Self, tests) in [
241+
% ('Hasher', 'sipHash13Tests'),
231242
% ('_SipHash13', 'sipHash13Tests'),
232243
% ('_SipHash24', 'sipHash24Tests')
233244
% ]:
234245

235246
SipHashTests.test("${Self}/combine(UnsafeRawBufferPointer)")
236247
.forEach(in: ${tests}) { test in
237-
var hasher = ${Self}(seed: test.seed)
248+
var hasher = ${Self}(_seed: test.seed)
238249
test.input.withUnsafeBytes { hasher.combine(bytes: $0) }
239250
let hash = hasher.finalize()
240-
expectEqual(test.output, hash)
251+
expectEqual(${Self}.HashValue(truncatingIfNeeded: test.output), hash)
241252
}
242253

243254
SipHashTests.test("${Self}/combine(UnsafeRawBufferPointer)/pattern")
244255
.forEach(in: cartesianProduct(${tests}, incrementalPatterns)) { test_ in
245256
let (test, pattern) = test_
246257

247-
var hasher = ${Self}(seed: test.seed)
258+
var hasher = ${Self}(_seed: test.seed)
248259
var chunkSizes = Loop(pattern).makeIterator()
249260
var startIndex = 0
250261
while startIndex != test.input.endIndex {
@@ -255,14 +266,15 @@ SipHashTests.test("${Self}/combine(UnsafeRawBufferPointer)/pattern")
255266
slice.withUnsafeBytes { hasher.combine(bytes: $0) }
256267
startIndex += chunkSize
257268
}
258-
expectEqual(test.output, hasher.finalize())
269+
let hash = hasher.finalize()
270+
expectEqual(${Self}.HashValue(truncatingIfNeeded: test.output), hash)
259271
}
260272

261273
% for data_type in ['UInt', 'UInt64', 'UInt32', 'UInt16', 'UInt8']:
262274
SipHashTests.test("${Self}._combine(${data_type})")
263275
.forEach(in: ${tests}) { test in
264276

265-
var hasher = ${Self}(seed: test.seed)
277+
var hasher = ${Self}(_seed: test.seed)
266278

267279
// Load little-endian chunks and combine them into the hasher.
268280
let bitWidth = ${data_type}.bitWidth
@@ -281,41 +293,32 @@ SipHashTests.test("${Self}._combine(${data_type})")
281293
}
282294
// Combine tail bytes.
283295
if count > 0 {
284-
hasher.combine(bytes: UInt64(truncatingIfNeeded: chunk), count: count)
296+
hasher._combine(bytes: UInt64(truncatingIfNeeded: chunk), count: count)
285297
}
286298

287299
let hash = hasher.finalize()
288-
expectEqual(test.output, hash)
289-
}
290-
291-
SipHashTests.test("${Self}/CombineAfterFinalize/${data_type}") {
292-
var hasher = ${Self}(seed: (0, 0))
293-
_ = hasher.finalize()
294-
expectCrashLater()
295-
hasher._combine(42 as ${data_type})
300+
expectEqual(${Self}.HashValue(truncatingIfNeeded: test.output), hash)
296301
}
297302
% end
298303

299-
SipHashTests.test("${Self}/CombineAfterFinalize/PartialUInt64") {
300-
var hasher = ${Self}(seed: (0, 0))
301-
_ = hasher.finalize()
302-
expectCrashLater()
303-
hasher.combine(bytes: 42, count: 1)
304-
}
305-
306-
SipHashTests.test("${Self}/CombineAfterFinalize/UnsafeRawBufferPointer") {
307-
var hasher = ${Self}(seed: (0, 0))
308-
_ = hasher.finalize()
309-
expectCrashLater()
310-
var v = 42
311-
withUnsafeBytes(of: &v) { hasher.combine(bytes: $0) }
312-
}
304+
SipHashTests.test("${Self}/OperationsAfterFinalize") {
305+
// Verify that finalize is nonmutating.
306+
var hasher1 = ${Self}(_seed: (0, 0))
307+
hasher1._combine(1 as UInt8)
308+
_ = hasher1.finalize()
309+
// Hasher is now consumed. The operations below are illegal, but this isn't
310+
// currently enforced. Check that the behavior matches that of a nonmutating
311+
// function.
312+
hasher1._combine(2 as UInt16)
313+
let hash1a = hasher1.finalize()
314+
let hash1b = hasher1.finalize()
315+
expectEqual(hash1a, hash1b)
313316

314-
SipHashTests.test("${Self}/FinalizeAfterFinalize") {
315-
var hasher = ${Self}(seed: (0, 0))
316-
_ = hasher.finalize()
317-
expectCrashLater()
318-
_ = hasher.finalize()
317+
var hasher2 = ${Self}(_seed: (0, 0))
318+
hasher2._combine(1 as UInt8)
319+
hasher2._combine(2 as UInt16)
320+
let hash2 = hasher2.finalize()
321+
expectEqual(hash1a, hash2)
319322
}
320323
% end
321324

0 commit comments

Comments
 (0)