Skip to content

Commit ee8480f

Browse files
committed
[Stdlib] Fix swift_setAtWritableKeyPath to check for ReferenceWritableKeyPaths.
Call through to swift_setAtReferenceWritableKeyPath in that case. This fixes an assertion failure (or worse) when upcasting a ReferenceWritableKeyPath and then using subscript(keyPath:) to write a value with it. rdar://problem/70609888
1 parent 768a085 commit ee8480f

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

stdlib/public/core/KeyPath.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,12 @@ func _setAtWritableKeyPath<Root, Value>(
19201920
keyPath: WritableKeyPath<Root, Value>,
19211921
value: __owned Value
19221922
) {
1923+
if type(of: keyPath).kind == .reference {
1924+
return _setAtReferenceWritableKeyPath(root: root,
1925+
keyPath: _unsafeUncheckedDowncast(keyPath,
1926+
to: ReferenceWritableKeyPath<Root, Value>.self),
1927+
value: value)
1928+
}
19231929
// TODO: we should be able to do this more efficiently than projecting.
19241930
let (addr, owner) = keyPath._projectMutableAddress(from: &root)
19251931
addr.pointee = value

test/stdlib/KeyPath.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,5 +1028,20 @@ keyPath.test("tail allocated c array") {
10281028
expectEqual(4, offset)
10291029
}
10301030

1031+
keyPath.test("ReferenceWritableKeyPath statically typed as WritableKeyPath") {
1032+
let inner = C<Int>(x: 42, y: nil, z: 43)
1033+
var outer = C<C<Int>>(x: 44, y: nil, z: inner)
1034+
let keyPath = \C<C<Int>>.z.x
1035+
let upcastKeyPath = keyPath as WritableKeyPath
1036+
1037+
expectEqual(outer[keyPath: keyPath], 42)
1038+
outer[keyPath: keyPath] = 43
1039+
expectEqual(outer[keyPath: keyPath], 43)
1040+
1041+
expectEqual(outer[keyPath: upcastKeyPath], 43)
1042+
outer[keyPath: upcastKeyPath] = 44
1043+
expectEqual(outer[keyPath: upcastKeyPath], 44)
1044+
}
1045+
10311046
runAllTests()
10321047

0 commit comments

Comments
 (0)