Skip to content

Commit 67a8720

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents b754860 + faeb55b commit 67a8720

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616
#include "swift/Sema/CSBindings.h"
1717
#include "TypeChecker.h"
18+
#include "swift/AST/ExistentialLayout.h"
1819
#include "swift/AST/GenericEnvironment.h"
1920
#include "swift/Sema/ConstraintGraph.h"
2021
#include "swift/Sema/ConstraintSystem.h"
@@ -1249,6 +1250,21 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
12491250

12501251
if (TypeVar->getImpl().isKeyPathType()) {
12511252
auto objectTy = type->lookThroughAllOptionalTypes();
1253+
1254+
// If contextual type is an existential with a superclass
1255+
// constraint, let's try to infer a key path type from it.
1256+
if (kind == AllowedBindingKind::Subtypes) {
1257+
if (type->isExistentialType()) {
1258+
auto layout = type->getExistentialLayout();
1259+
if (auto superclass = layout.explicitSuperclass) {
1260+
if (isKnownKeyPathType(superclass)) {
1261+
type = superclass;
1262+
objectTy = superclass;
1263+
}
1264+
}
1265+
}
1266+
}
1267+
12521268
if (!(isKnownKeyPathType(objectTy) || objectTy->is<AnyFunctionType>()))
12531269
return llvm::None;
12541270
}

test/expr/unary/keypath/keypath.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,3 +1181,24 @@ func f_56854() {
11811181
// expected-note@-1 2 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
11821182
}
11831183
}
1184+
1185+
// rdar://93103421 - Key path type inference doesn't work when the context is an existential type with a key-path superclass
1186+
extension KeyPath : P {
1187+
var member: String { "" }
1188+
}
1189+
1190+
func test_keypath_inference_from_existentials() {
1191+
struct A<T> : P {
1192+
var member: String { "a" }
1193+
var other: T { fatalError() }
1194+
}
1195+
1196+
func test<T, U>(_: any P & KeyPath<A<T>, U>, _: T) {
1197+
}
1198+
1199+
let _: any P & KeyPath<A<Int>, String> = \.member // Ok
1200+
let _: (any P & KeyPath<A<Int>, String>) = \.member // Ok
1201+
1202+
test(\.other, 42) // Ok
1203+
test(\.member, "") // Ok
1204+
}

0 commit comments

Comments
 (0)