Skip to content

Commit 6fd6c16

Browse files
committed
[CSSimplify] Key path should use a default type is contextual type is a placeholder
If there is something wrong with the context, let's assign a default KeyPath type to the key path literal to avoid propagating placeholder into the key path inference.
1 parent 4830c5b commit 6fd6c16

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11650,6 +11650,13 @@ bool ConstraintSystem::resolveKeyPath(TypeVariableType *typeVar,
1165011650
contextualType = BoundGenericType::get(
1165111651
keyPathTy->getDecl(), keyPathTy->getParent(), {root, value});
1165211652
}
11653+
} else if (contextualType->isPlaceholder()) {
11654+
auto root = simplifyType(getKeyPathRootType(keyPath));
11655+
if (!(root->isTypeVariableOrMember() || root->isPlaceholder())) {
11656+
auto value = getKeyPathValueType(keyPath);
11657+
contextualType =
11658+
BoundGenericType::get(ctx.getKeyPathDecl(), Type(), {root, value});
11659+
}
1165311660
}
1165411661
}
1165511662

@@ -12222,6 +12229,16 @@ ConstraintSystem::simplifyKeyPathConstraint(
1222212229
tv->getImpl().canBindToHole();
1222312230
})) {
1222412231
(void)tryMatchRootAndValueFromType(keyPathTy);
12232+
12233+
// If the type of the key path is not yet resolved simplifying this
12234+
// constraint would disconnect it from root and value, let's bind it
12235+
// to a placeholder type to make sure this doesn't happen.
12236+
if (auto *typeVar = keyPathTy->getAs<TypeVariableType>()) {
12237+
return matchTypes(keyPathTy, PlaceholderType::get(Context, typeVar),
12238+
ConstraintKind::Bind, subflags,
12239+
locator.getBaseLocator());
12240+
}
12241+
1222512242
return SolutionKind::Solved;
1222612243
}
1222712244
}

test/expr/unary/keypath/keypath.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,8 +1065,7 @@ func f_56996() {
10651065
func f_55805() {
10661066
let _: KeyPath<String?, Int?> = \.utf8.count
10671067
// expected-error@-1 {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'utf8' of unwrapped type 'String'}}
1068-
// expected-error@-2 {{cannot assign value of type 'KeyPath<String?, Int>' to type 'KeyPath<String?, Int?>'}}
1069-
// expected-note@-3 {{arguments to generic parameter 'Value' ('Int' and 'Int?') are expected to be equal}}
1068+
// expected-error@-2 {{key path value type 'Int' cannot be converted to contextual type 'Int?'}}
10701069
}
10711070

10721071
// rdar://74711236 - crash due to incorrect member access in key path

0 commit comments

Comments
 (0)