Skip to content

Commit 7ff82b3

Browse files
committed
[stdlib] Dictionary.updateValue(_:,forKey:): Don’t overwrite the existing key
Replacing the old key with the new is unnecessary and somewhat surprising. It is also harmful to some usecases. rdar://problem/32144087 # Conflicts: # stdlib/public/core/NativeDictionary.swift
1 parent 66b1830 commit 7ff82b3

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

stdlib/public/core/NativeDictionary.swift

-8
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,6 @@ extension _NativeDictionary { // Insertions
416416
if found {
417417
let oldValue = (_values + bucket.offset).move()
418418
(_values + bucket.offset).initialize(to: value)
419-
// FIXME: Replacing the old key with the new is unnecessary, unintuitive,
420-
// and actively harmful to some usecases. We shouldn't do it.
421-
// rdar://problem/32144087
422-
(_keys + bucket.offset).pointee = key
423419
return oldValue
424420
}
425421
_insert(at: bucket, key: key, value: value)
@@ -435,10 +431,6 @@ extension _NativeDictionary { // Insertions
435431
let (bucket, found) = mutatingFind(key, isUnique: isUnique)
436432
if found {
437433
(_values + bucket.offset).pointee = value
438-
// FIXME: Replacing the old key with the new is unnecessary, unintuitive,
439-
// and actively harmful to some usecases. We shouldn't do it.
440-
// rdar://problem/32144087
441-
(_keys + bucket.offset).pointee = key
442434
} else {
443435
_insert(at: bucket, key: key, value: value)
444436
}

validation-test/stdlib/Dictionary.swift

+27-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ DictionaryTestSuite.test("COW.Fast.UpdateValueForKeyDoesNotReallocate") {
411411
}
412412
}
413413

414-
DictionaryTestSuite.test("COW.Slow.AddDoesNotReallocate") {
414+
DictionaryTestSuite.test("COW.Slow.UpdateValueForKeyDoesNotReallocate") {
415415
do {
416416
var d1 = getCOWSlowDictionary()
417417
let identity1 = d1._rawIdentifier()
@@ -4642,6 +4642,32 @@ DictionaryTestSuite.test("removeAt") {
46424642
}
46434643
}
46444644

4645+
DictionaryTestSuite.test("updateValue") {
4646+
let key1 = TestKeyTy(42)
4647+
let key2 = TestKeyTy(42)
4648+
let value1 = TestValueTy(1)
4649+
let value2 = TestValueTy(2)
4650+
4651+
var d: [TestKeyTy: TestValueTy] = [:]
4652+
4653+
expectNil(d.updateValue(value1, forKey: key1))
4654+
4655+
expectEqual(d.count, 1)
4656+
let index1 = d.index(forKey: key2)
4657+
expectNotNil(index1)
4658+
expectTrue(d[index1!].key === key1)
4659+
expectTrue(d[index1!].value === value1)
4660+
4661+
expectTrue(d.updateValue(value2, forKey: key2) === value1)
4662+
4663+
expectEqual(d.count, 1)
4664+
let index2 = d.index(forKey: key2)
4665+
expectEqual(index1, index2)
4666+
// We expect updateValue to keep the original key in place.
4667+
expectTrue(d[index2!].key === key1) // Not key2
4668+
expectTrue(d[index2!].value === value2)
4669+
}
4670+
46454671
DictionaryTestSuite.test("localHashSeeds") {
46464672
// With global hashing, copying elements in hash order between hash tables
46474673
// can become quadratic. (See https://bugs.swift.org/browse/SR-3268)

0 commit comments

Comments
 (0)