[CSApply] Optional chaining forces key path component to be r-value

Key path components with optional chaining unlike other places
don't propagate l-value through optionals.

Resolves: rdar://123638701
This commit is contained in:
Pavel Yaskevich
2024-02-26 13:08:58 -08:00
parent 03194eb4b1
commit 7ad80b8ce0
2 changed files with 22 additions and 1 deletions

View File

@@ -5116,7 +5116,8 @@ namespace {
!componentTy->getWithoutSpecifierType()->isEqual(leafTy)) { !componentTy->getWithoutSpecifierType()->isEqual(leafTy)) {
auto component = KeyPathExpr::Component::forOptionalWrap(leafTy); auto component = KeyPathExpr::Component::forOptionalWrap(leafTy);
resolvedComponents.push_back(component); resolvedComponents.push_back(component);
componentTy = OptionalType::get(componentTy); // Optional chaining forces the component to be r-value.
componentTy = OptionalType::get(componentTy->getWithoutSpecifierType());
} }
// Set the resolved components, and cache their types. // Set the resolved components, and cache their types.

View File

@@ -652,3 +652,23 @@ struct Test {
var codingPath: [any CodingKey] { codingStack.map(\.key) } var codingPath: [any CodingKey] { codingStack.map(\.key) }
// CHECK: keypath $KeyPath<CodingStackEntry, URICoderCodingKey>, (root $CodingStackEntry; stored_property #CodingStackEntry.key : $URICoderCodingKey) // CHECK: keypath $KeyPath<CodingStackEntry, URICoderCodingKey>, (root $CodingStackEntry; stored_property #CodingStackEntry.key : $URICoderCodingKey)
} }
// rdar://123638701 - Make sure that optional chaining forces loads.
func test_optional_chaining_with_function_conversion() {
class Storage {}
class Elements {
var db: Storage = Storage()
}
class Source {
var elements: Elements? = nil
}
func test(data: [Source]) {
// CHECK: {{.*}} = keypath $KeyPath<Source, Optional<Storage>>
_ = data.compactMap(\.elements?.db)
// CHECK: {{.*}} = keypath $KeyPath<Source, Storage>
_ = data.compactMap(\.elements!.db)
}
}