Skip to content

Commit 0e1abc9

Browse files
committed
[CSBindings] Add special handling for key path default bindings
If there are no contextual types available but capability of key path could be inferred, let's turn default into a real binding.
1 parent 4ace882 commit 0e1abc9

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,10 +620,7 @@ class BindingSet {
620620

621621
void addLiteralRequirement(Constraint *literal);
622622

623-
void addDefault(Constraint *constraint) {
624-
auto defaultTy = constraint->getSecondType();
625-
Defaults.insert({defaultTy->getCanonicalType(), constraint});
626-
}
623+
void addDefault(Constraint *constraint);
627624

628625
/// Check whether the given binding set covers any of the
629626
/// literal protocols associated with this type variable.

lib/Sema/CSBindings.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ bool BindingSet::isDelayed() const {
9494
}
9595
}
9696

97+
// Delay key path literal type binding until there is at least
98+
// one contextual binding (or default is promoted into a binding).
99+
if (TypeVar->getImpl().isKeyPathType() && Bindings.empty())
100+
return true;
101+
97102
if (isHole()) {
98103
auto *locator = TypeVar->getImpl().getLocator();
99104
assert(locator && "a hole without locator?");
@@ -169,6 +174,12 @@ bool BindingSet::isPotentiallyIncomplete() const {
169174
if (Info.isGenericParameter())
170175
return true;
171176

177+
// Key path literal type is incomplete until there is a
178+
// contextual type or key path is resolved enough to infer
179+
// capability and promote default into a binding.
180+
if (TypeVar->getImpl().isKeyPathType())
181+
return Bindings.empty();
182+
172183
// If current type variable is associated with a code completion token
173184
// it's possible that it doesn't have enough contextual information
174185
// to be resolved to anything so let's delay considering it until everything
@@ -873,6 +884,44 @@ void PotentialBindings::addDefault(Constraint *constraint) {
873884
Defaults.insert(constraint);
874885
}
875886

887+
void BindingSet::addDefault(Constraint *constraint) {
888+
auto defaultTy = constraint->getSecondType();
889+
890+
if (TypeVar->getImpl().isKeyPathType() && Bindings.empty()) {
891+
if (constraint->getKind() == ConstraintKind::FallbackType) {
892+
if (auto capability = CS.inferKeyPathLiteralCapability(TypeVar)) {
893+
auto *keyPathType = defaultTy->castTo<BoundGenericType>();
894+
895+
auto root = keyPathType->getGenericArgs()[0];
896+
auto value = keyPathType->getGenericArgs()[1];
897+
898+
auto &ctx = CS.getASTContext();
899+
900+
switch (*capability) {
901+
case KeyPathCapability::ReadOnly:
902+
break;
903+
904+
case KeyPathCapability::Writable:
905+
keyPathType = BoundGenericType::get(ctx.getWritableKeyPathDecl(),
906+
/*parent=*/Type(), {root, value});
907+
break;
908+
909+
case KeyPathCapability::ReferenceWritable:
910+
keyPathType =
911+
BoundGenericType::get(ctx.getReferenceWritableKeyPathDecl(),
912+
/*parent=*/Type(), {root, value});
913+
break;
914+
}
915+
916+
addBinding({keyPathType, AllowedBindingKind::Exact, constraint});
917+
return;
918+
}
919+
}
920+
}
921+
922+
Defaults.insert({defaultTy->getCanonicalType(), constraint});
923+
}
924+
876925
bool LiteralRequirement::isCoveredBy(Type type, ConstraintSystem &CS) const {
877926
auto coversDefaultType = [](Type type, Type defaultType) -> bool {
878927
if (!defaultType->hasUnboundGenericType())

0 commit comments

Comments
 (0)