I think the way you get this to work is to force the Dictionary into the _modify accessor:
extension Dictionary {
mutating func setIfNotAlready(_ value: @autoclosure () -> Value, forKey key: Key) {
self[key].setIfNil(value)
}
}
extension Optional {
fileprivate mutating func setIfNil(_ newValue: () -> Wrapped) {
if self == nil {
self = .some(newValue())
}
}
}
You can see the code for the _modify accessor here, which includes only one call to mutatingFind which does the actual hashing. All other calls have already found a bucket, so no further hashing is required to perform the insertion.