Skip to content

Commit a84a3a8

Browse files
committed
[Stdlib] Fix _swift_modifyAtWritableKeyPath_impl to check for ReferenceWritableKeyPaths.
Call through to _swift_modifyAtReferenceWritableKeyPath_impl in that case. This fixes an assertion failure (or worse) when upcasting a ReferenceWritableKeyPath and then using subscript(keyPath:) to modify a value with it. rdar://74191390
1 parent 22acb2f commit a84a3a8

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

Diff for: stdlib/public/core/KeyPath.swift

+5
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,11 @@ func _modifyAtWritableKeyPath_impl<Root, Value>(
19321932
root: inout Root,
19331933
keyPath: WritableKeyPath<Root, Value>
19341934
) -> (UnsafeMutablePointer<Value>, AnyObject?) {
1935+
if type(of: keyPath).kind == .reference {
1936+
return _modifyAtReferenceWritableKeyPath_impl(root: root,
1937+
keyPath: _unsafeUncheckedDowncast(keyPath,
1938+
to: ReferenceWritableKeyPath<Root, Value>.self))
1939+
}
19351940
return keyPath._projectMutableAddress(from: &root)
19361941
}
19371942

Diff for: test/stdlib/KeyPath.swift

+10
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,16 @@ keyPath.test("ReferenceWritableKeyPath statically typed as WritableKeyPath") {
10411041
expectEqual(outer[keyPath: upcastKeyPath], 43)
10421042
outer[keyPath: upcastKeyPath] = 44
10431043
expectEqual(outer[keyPath: upcastKeyPath], 44)
1044+
1045+
func setWithInout<T>(_ lhs: inout T, _ rhs: T) { lhs = rhs }
1046+
1047+
expectEqual(outer[keyPath: keyPath], 44)
1048+
setWithInout(&outer[keyPath: keyPath], 45);
1049+
expectEqual(outer[keyPath: keyPath], 45)
1050+
1051+
expectEqual(outer[keyPath: upcastKeyPath], 45)
1052+
setWithInout(&outer[keyPath: upcastKeyPath], 46)
1053+
expectEqual(outer[keyPath: upcastKeyPath], 46)
10441054
}
10451055

10461056
runAllTests()

0 commit comments

Comments
 (0)