Skip to content

Commit ab41167

Browse files
authored
Merge pull request #67948 from xedin/rdar-113760727
[CSSimplify] Adjust {Any, Partial}KeyPath bindings right before resolving
2 parents b2f46ba + b34f972 commit ab41167

File tree

3 files changed

+61
-37
lines changed

3 files changed

+61
-37
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,35 +1253,6 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
12531253
auto objectTy = type->lookThroughAllOptionalTypes();
12541254
if (!isKnownKeyPathType(objectTy))
12551255
return llvm::None;
1256-
1257-
auto &ctx = CS.getASTContext();
1258-
auto *keyPathTypeLoc = TypeVar->getImpl().getLocator();
1259-
auto *keyPath = castToExpr<KeyPathExpr>(keyPathTypeLoc->getAnchor());
1260-
// `AnyKeyPath` and `PartialKeyPath` represent type-erased versions of
1261-
// `KeyPath<T, V>`.
1262-
//
1263-
// In situations where `AnyKeyPath` or `PartialKeyPath` cannot be used
1264-
// directly i.e. passing an argument to a parameter represented by a
1265-
// `AnyKeyPath` or `PartialKeyPath`, let's attempt a `KeyPath` binding which
1266-
// would then be converted to a `AnyKeyPath` or `PartialKeyPath` since there
1267-
// is a subtype relationship between them.
1268-
if (objectTy->isAnyKeyPath()) {
1269-
auto root = CS.getKeyPathRootType(keyPath);
1270-
auto value = CS.getKeyPathValueType(keyPath);
1271-
1272-
type = BoundGenericType::get(ctx.getKeyPathDecl(), Type(),
1273-
{root, value});
1274-
} else if (objectTy->isPartialKeyPath() &&
1275-
kind == AllowedBindingKind::Subtypes) {
1276-
auto rootTy = objectTy->castTo<BoundGenericType>()->getGenericArgs()[0];
1277-
// Since partial key path is an erased version of `KeyPath`, the value
1278-
// type would never be used, which means that binding can use
1279-
// type variable generated for a result of key path expression.
1280-
auto valueTy = CS.getKeyPathValueType(keyPath);
1281-
1282-
type = BoundGenericType::get(ctx.getKeyPathDecl(), Type(),
1283-
{rootTy, valueTy});
1284-
}
12851256
}
12861257

12871258
if (auto *locator = TypeVar->getImpl().getLocator()) {

lib/Sema/CSSimplify.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11608,19 +11608,52 @@ bool ConstraintSystem::resolveKeyPath(TypeVariableType *typeVar,
1160811608
ConstraintLocatorBuilder locator) {
1160911609
auto *keyPathLocator = typeVar->getImpl().getLocator();
1161011610
auto *keyPath = castToExpr<KeyPathExpr>(keyPathLocator->getAnchor());
11611+
1161111612
if (keyPath->hasSingleInvalidComponent()) {
1161211613
assignFixedType(typeVar, contextualType);
1161311614
return true;
1161411615
}
11615-
if (auto *BGT = contextualType->getAs<BoundGenericType>()) {
11616-
auto args = BGT->getGenericArgs();
11617-
if (isKnownKeyPathType(contextualType) && args.size() >= 1) {
11618-
auto root = BGT->getGenericArgs()[0];
1161911616

11620-
auto *keyPathValueTV = getKeyPathValueType(keyPath);
11621-
contextualType = BoundGenericType::get(
11622-
args.size() == 1 ? getASTContext().getKeyPathDecl() : BGT->getDecl(),
11623-
/*parent=*/Type(), {root, keyPathValueTV});
11617+
auto objectTy = contextualType->lookThroughAllOptionalTypes();
11618+
{
11619+
auto &ctx = getASTContext();
11620+
// `AnyKeyPath` and `PartialKeyPath` represent type-erased versions of
11621+
// `KeyPath<T, V>`.
11622+
//
11623+
// In situations where `AnyKeyPath` or `PartialKeyPath` cannot be used
11624+
// directly i.e. passing an argument to a parameter represented by a
11625+
// `AnyKeyPath` or `PartialKeyPath`, let's attempt a `KeyPath` binding which
11626+
// would then be converted to a `AnyKeyPath` or `PartialKeyPath` since there
11627+
// is a subtype relationship between them.
11628+
if (objectTy->isAnyKeyPath()) {
11629+
auto root = getKeyPathRootType(keyPath);
11630+
auto value = getKeyPathValueType(keyPath);
11631+
11632+
contextualType =
11633+
BoundGenericType::get(ctx.getKeyPathDecl(), Type(), {root, value});
11634+
} else if (objectTy->isPartialKeyPath()) {
11635+
auto rootTy = objectTy->castTo<BoundGenericType>()->getGenericArgs()[0];
11636+
// Since partial key path is an erased version of `KeyPath`, the value
11637+
// type would never be used, which means that binding can use
11638+
// type variable generated for a result of key path expression.
11639+
auto valueTy = getKeyPathValueType(keyPath);
11640+
11641+
contextualType = BoundGenericType::get(ctx.getKeyPathDecl(), Type(),
11642+
{rootTy, valueTy});
11643+
} else if (isKnownKeyPathType(objectTy)) {
11644+
auto *keyPathTy = objectTy->castTo<BoundGenericType>();
11645+
auto args = keyPathTy->getGenericArgs();
11646+
assert(args.size() == 2);
11647+
11648+
auto root = args.front();
11649+
auto value = getKeyPathValueType(keyPath);
11650+
11651+
// Make sure that key path always gets a chance to infer its
11652+
// value type from the member chain.
11653+
if (!value->isEqual(args.back())) {
11654+
contextualType = BoundGenericType::get(
11655+
keyPathTy->getDecl(), keyPathTy->getParent(), {root, value});
11656+
}
1162411657
}
1162511658
}
1162611659

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct Value {
4+
var data: String
5+
}
6+
7+
func testAnyKeyPath<T>(field: AnyKeyPath, _: UnsafePointer<T>) {}
8+
func testPartialKeyPath<T>(field: PartialKeyPath<T>, _: UnsafePointer<T>) {}
9+
10+
struct Test {
11+
func test(ptr: UnsafePointer<Int64>) {
12+
ptr.withMemoryRebound(to: Value.self, capacity: 2) { newPtr in
13+
for idx in 0 ..< 2 {
14+
var elt = newPtr[idx]
15+
testAnyKeyPath(field: \Value.data, &elt)
16+
testPartialKeyPath(field: \Value.data, &elt)
17+
}
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)