From 7ad80b8ce016b51d9069c73dce904eb210f7ef5f Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 26 Feb 2024 13:08:58 -0800 Subject: [PATCH] [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 --- lib/Sema/CSApply.cpp | 3 ++- test/SILGen/keypaths.swift | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index f3145e09554ff..db66fa8f4dda9 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5116,7 +5116,8 @@ namespace { !componentTy->getWithoutSpecifierType()->isEqual(leafTy)) { auto component = KeyPathExpr::Component::forOptionalWrap(leafTy); 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. diff --git a/test/SILGen/keypaths.swift b/test/SILGen/keypaths.swift index c45191840b2bd..b6881a4d58c2b 100644 --- a/test/SILGen/keypaths.swift +++ b/test/SILGen/keypaths.swift @@ -652,3 +652,23 @@ struct Test { var codingPath: [any CodingKey] { codingStack.map(\.key) } // CHECK: keypath $KeyPath, (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> + _ = data.compactMap(\.elements?.db) + // CHECK: {{.*}} = keypath $KeyPath + _ = data.compactMap(\.elements!.db) + } +}