Skip to content

Commit b17ec0e

Browse files
committed
[CSSimplify] Broaden delay of the key path assignment
If key path is connected to a disjunction directly or indirectly (i.e. via ApplicableFunction constraint) do not attempt to bind it until disjunction is taken, otherwise there is a risk to miss a valid keypath-to-function conversion.
1 parent cc0e621 commit b17ec0e

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12409,7 +12409,8 @@ ConstraintSystem::simplifyKeyPathConstraint(
1240912409
return SolutionKind::Solved;
1241012410
} else if (!anyComponentsUnresolved ||
1241112411
(definitelyKeyPathType && capability == ReadOnly)) {
12412-
// If key path is connected to a function application it cannot be
12412+
// If key path is connected to a disjunction (i.e. through coercion
12413+
// or used as an argument to a function/subscipt call) it cannot be
1241312414
// bound until the choice is selected because it's undetermined
1241412415
// until then whether key path is implicitly converted to a function
1241512416
// type or not.
@@ -12436,7 +12437,8 @@ ConstraintSystem::simplifyKeyPathConstraint(
1243612437
typeVar, OptionalWrappingDirection::Unwrap,
1243712438
[&](Constraint *match, TypeVariableType *) {
1243812439
return match->getKind() ==
12439-
ConstraintKind::ApplicableFunction;
12440+
ConstraintKind::ApplicableFunction ||
12441+
match->getKind() == ConstraintKind::Disjunction;
1244012442
})) {
1244112443
formUnsolved();
1244212444
} else {

test/expr/unary/keypath/keypath.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,3 +1213,14 @@ func keypath_to_func_conversion_as_arg_to_overloaded_func() {
12131213
test(arr, \Data.value) // Ok
12141214
}
12151215
}
1216+
1217+
// https://github.com/apple/swift/issues/55436
1218+
func test_keypath_coercion_to_function() {
1219+
struct User {
1220+
let email: String
1221+
}
1222+
1223+
let users = [User]()
1224+
let fn = \User.email as (User) -> String // Ok
1225+
_ = users.map(fn) // Ok
1226+
}

0 commit comments

Comments
 (0)