Skip to content

Commit 4830c5b

Browse files
committed
[CSSimplify] Unwrap of key path root can only yield one type
For methods there are two possibilities - force unwrap and conditional, that's why we need a disjunction with two choices. This is not the case for key path root type it could only be force unwrapped.
1 parent b095158 commit 4830c5b

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10845,6 +10845,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
1084510845
if (result.ViableCandidates.empty() && result.UnviableCandidates.empty())
1084610846
return fixMissingMember(origBaseTy, memberTy, locator);
1084710847

10848+
bool baseIsKeyPathRootType = [&]() {
10849+
auto keyPathComponent =
10850+
locator->getLastElementAs<LocatorPathElt::KeyPathComponent>();
10851+
return keyPathComponent && keyPathComponent->getIndex() == 0;
10852+
}();
10853+
1084810854
// The result of the member access can either be the expected member type
1084910855
// (for '!' or optional members with '?'), or the original member type
1085010856
// with one extra level of optionality ('?' with non-optional members).
@@ -10858,13 +10864,17 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
1085810864
*this, ConstraintKind::Bind,
1085910865
UnwrapOptionalBase::create(*this, member, baseObjTy, locator),
1086010866
memberTy, innerTV, locator);
10861-
auto optionalResult = Constraint::createFixed(
10862-
*this, ConstraintKind::Bind,
10863-
UnwrapOptionalBase::createWithOptionalResult(*this, member,
10864-
baseObjTy, locator),
10865-
optTy, memberTy, locator);
1086610867
optionalities.push_back(nonoptionalResult);
10867-
optionalities.push_back(optionalResult);
10868+
10869+
if (!baseIsKeyPathRootType) {
10870+
auto optionalResult = Constraint::createFixed(
10871+
*this, ConstraintKind::Bind,
10872+
UnwrapOptionalBase::createWithOptionalResult(*this, member,
10873+
baseObjTy, locator),
10874+
optTy, memberTy, locator);
10875+
optionalities.push_back(optionalResult);
10876+
}
10877+
1086810878
addDisjunctionConstraint(optionalities, locator);
1086910879

1087010880
// Look through one level of optional.

test/expr/unary/keypath/keypath.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,8 +1065,8 @@ 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 {{value of optional type 'String.UTF8View?' must be unwrapped to refer to member 'count' of wrapped base type 'String.UTF8View'}}
1069-
// expected-note@-3 {{chain the optional using '?' to access member 'count' only for non-'nil' base values}}
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}}
10701070
}
10711071

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

0 commit comments

Comments
 (0)