I bumped into what I guess might be a bug in the standard library or compiler.
The actual code and situation where it happened is quite involved and this is the smallest program I could make that reproduces the bug:
func randomString() -> String {
(0..<10_000).map({ _ in Bool.random() ? "å" : "ä" }).joined()
}
extension String {
func randomSubstring() -> Substring {
let i = indices.dropLast(1).randomElement()!
return self[i...i]
}
}
func test() {
let s1 = randomString()
let s2 = randomString()
var dict = [Substring : Int]()
for _ in 0 ..< 1000 {
let a = s1.randomSubstring()
let b = s2.randomSubstring()
dict[a, default: 0] += 1
dict[b, default: 0] += 1
}
dict.forEach { print($0, $1) }
}
test()
Typical results when compiling and running this program a couple of times (the dictionary sometimes contains duplicate keys, and sometimes it crashes):
% swiftc --version
swift-driver version: 1.45.2 Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)
Target: x86_64-apple-macosx12.0
% swiftc -O test.swift && ./test
ä 492
å 1002
ä 506
% swiftc -O test.swift && ./test
ä 970
å 1030
% swiftc -O test.swift && ./test
å 498
ä 479
å 520
ä 503
% swiftc -O test.swift && ./test
Fatal error: Duplicate keys of type 'Substring' were found in a Dictionary.
This usually means either that the type violates Hashable's requirements, or
that members of such a dictionary were mutated after insertion.
Note that if the "å" and "ö" Characters are changed to eg "x" and "y", then it will behave as expected (never print duplicate Dictionary keys and never crash):
% swiftc -O test.swift && ./test
y 1004
x 996
% swiftc -O test.swift && ./test
y 1016
x 984
% swiftc -O test.swift && ./test
x 993
y 1007