Skip to content

Commit a293ce1

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
1 parent 649d310 commit a293ce1

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

stdlib/public/core/NativeDictionary.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,6 @@ extension _NativeDictionary { // Insertions
410410
if found {
411411
let oldValue = (_values + index.bucket).move()
412412
(_values + index.bucket).initialize(to: value)
413-
// FIXME: Replacing the old key with the new is unnecessary, unintuitive,
414-
// and actively harmful to some usecases. We shouldn't do it.
415-
// rdar://problem/32144087
416-
(_keys + index.bucket).pointee = key
417413
return oldValue
418414
}
419415
_insert(at: index, key: key, value: value)
@@ -429,10 +425,6 @@ extension _NativeDictionary { // Insertions
429425
let (index, found) = mutatingFind(key, isUnique: isUnique)
430426
if found {
431427
(_values + index.bucket).pointee = value
432-
// FIXME: Replacing the old key with the new is unnecessary, unintuitive,
433-
// and actively harmful to some usecases. We shouldn't do it.
434-
// rdar://problem/32144087
435-
(_keys + index.bucket).pointee = key
436428
} else {
437429
_insert(at: index, key: key, value: value)
438430
}

validation-test/stdlib/Dictionary.swift

Lines changed: 27 additions & 1 deletion
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)