Skip to content

Commit 19e9cb0

Browse files
committed
[CSSimplify] Delay simplification of key path constraint until key path type is bound
Let the inference drive key path literal resolution, this fixes a problem where key path is bound too eagerly.
1 parent 0e1abc9 commit 19e9cb0

File tree

1 file changed

+19
-48
lines changed

1 file changed

+19
-48
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11729,7 +11729,6 @@ bool ConstraintSystem::resolveKeyPath(TypeVariableType *typeVar,
1172911729

1173011730
auto root = args.front();
1173111731
auto value = getKeyPathValueType(keyPath);
11732-
1173311732
// Make sure that key path always gets a chance to infer its
1173411733
// value type from the member chain.
1173511734
if (!value->isEqual(args.back())) {
@@ -12212,6 +12211,19 @@ ConstraintSystem::simplifyKeyPathConstraint(
1221212211
bool definitelyKeyPathType = false;
1221312212
bool resolveAsMultiArgFuncFix = false;
1221412213

12214+
auto formUnsolved = [&]() -> SolutionKind {
12215+
if (flags.contains(TMF_GenerateConstraints)) {
12216+
addUnsolvedConstraint(Constraint::create(
12217+
*this, ConstraintKind::KeyPath, keyPathTy, rootTy, valueTy,
12218+
locator.getBaseLocator(), componentTypeVars));
12219+
return SolutionKind::Solved;
12220+
}
12221+
return SolutionKind::Unsolved;
12222+
};
12223+
12224+
if (keyPathTy->isTypeVariableOrMember())
12225+
return formUnsolved();
12226+
1221512227
auto tryMatchRootAndValueFromType = [&](Type type,
1221612228
bool allowPartial = true) -> bool {
1221712229
Type boundRoot = Type(), boundValue = Type();
@@ -12493,60 +12505,19 @@ ConstraintSystem::simplifyKeyPathConstraint(
1249312505
kpDecl = getASTContext().getWritableKeyPathDecl();
1249412506
}
1249512507

12496-
auto formUnsolved = [&]() {
12497-
addUnsolvedConstraint(Constraint::create(
12498-
*this, ConstraintKind::KeyPath, keyPathTy, rootTy, valueTy,
12499-
locator.getBaseLocator(), componentTypeVars));
12500-
};
12501-
1250212508
auto loc = locator.getBaseLocator();
1250312509
if (definitelyFunctionType) {
1250412510
increaseScore(SK_FunctionConversion, locator);
1250512511
return SolutionKind::Solved;
1250612512
} else if (!anyComponentsUnresolved ||
1250712513
(definitelyKeyPathType && capability == ReadOnly)) {
12508-
// If key path is connected to a disjunction (i.e. through coercion
12509-
// or used as an argument to a function/subscipt call) it cannot be
12510-
// bound until the choice is selected because it's undetermined
12511-
// until then whether key path is implicitly converted to a function
12512-
// type or not.
12513-
//
12514-
// \code
12515-
// struct Data {
12516-
// var value: Int = 42
12517-
// }
12518-
//
12519-
// func test<S: Sequence>(_: S, _: (S.Element) -> Int) {}
12520-
// func test<C: Collection>(_: C, _: (C.Element) -> Int) {}
12521-
//
12522-
// func test(arr: [Data]) {
12523-
// test(arr, \Data.value)
12524-
// }
12525-
// \endcode
12526-
//
12527-
// In this example if we did allow to bind the key path before
12528-
// an overload of `test` is selected, we'd end up with no solutions
12529-
// because the type of the key path expression is actually: '(Data) -> Int'
12530-
// and not 'WritableKeyPath<Data, Int>`.
12531-
auto *typeVar = keyPathTy->getAs<TypeVariableType>();
12532-
if (typeVar && findConstraintThroughOptionals(
12533-
typeVar, OptionalWrappingDirection::Unwrap,
12534-
[&](Constraint *match, TypeVariableType *) {
12535-
return match->getKind() ==
12536-
ConstraintKind::ApplicableFunction ||
12537-
match->getKind() == ConstraintKind::Disjunction;
12538-
})) {
12539-
formUnsolved();
12540-
} else {
12541-
auto resolvedKPTy =
12542-
BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
12543-
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind,
12544-
subflags, loc);
12545-
}
12546-
} else {
12547-
formUnsolved();
12514+
auto resolvedKPTy =
12515+
BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
12516+
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
12517+
loc);
1254812518
}
12549-
return SolutionKind::Solved;
12519+
12520+
return formUnsolved();
1255012521
}
1255112522

1255212523
ConstraintSystem::SolutionKind

0 commit comments

Comments
 (0)