Skip to content

Commit 5a6c562

Browse files
committed
[CSSimplify] Adjust locators associated with keypath root/value matching constraints
`tryMatchRootAndValueFromType` anchored both root and value match constraints directly on the key path expression. That is incorrect because we have special locators for that.
1 parent 6a1783d commit 5a6c562

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5958,14 +5958,6 @@ bool ConstraintSystem::repairFailures(
59585958
if (repairViaBridgingCast(*this, lhs, rhs, conversionsOrFixes, locator))
59595959
break;
59605960

5961-
// If both types are key path, the only differences
5962-
// between them are mutability and/or root, value type mismatch.
5963-
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
5964-
auto *fix = KeyPathContextualMismatch::create(
5965-
*this, lhs, rhs, getConstraintLocator(locator));
5966-
conversionsOrFixes.push_back(fix);
5967-
}
5968-
59695961
if (lhs->is<FunctionType>() && !rhs->is<AnyFunctionType>() &&
59705962
isExpr<ClosureExpr>(anchor)) {
59715963
auto *fix = ContextualMismatch::create(*this, lhs, rhs,
@@ -6608,8 +6600,20 @@ bool ConstraintSystem::repairFailures(
66086600
if (hasFixFor(lastCompLoc, FixKind::AllowTypeOrInstanceMember))
66096601
return true;
66106602

6603+
auto *keyPathLoc = getConstraintLocator(anchor);
6604+
6605+
if (hasFixFor(keyPathLoc))
6606+
return true;
6607+
6608+
if (auto contextualInfo = getContextualTypeInfo(anchor)) {
6609+
if (hasFixFor(getConstraintLocator(
6610+
keyPathLoc,
6611+
LocatorPathElt::ContextualType(contextualInfo->purpose))))
6612+
return true;
6613+
}
6614+
66116615
conversionsOrFixes.push_back(IgnoreContextualType::create(
6612-
*this, lhs, rhs, getConstraintLocator(anchor)));
6616+
*this, lhs, rhs, keyPathLoc));
66136617
break;
66146618
}
66156619
default:
@@ -12150,12 +12154,14 @@ ConstraintSystem::simplifyKeyPathConstraint(
1215012154
}
1215112155

1215212156
if (boundRoot &&
12153-
matchTypes(boundRoot, rootTy, ConstraintKind::Bind, subflags, locator)
12157+
matchTypes(rootTy, boundRoot, ConstraintKind::Bind, subflags,
12158+
locator.withPathElement(ConstraintLocator::KeyPathRoot))
1215412159
.isFailure())
1215512160
return false;
1215612161

1215712162
if (boundValue &&
12158-
matchTypes(boundValue, valueTy, ConstraintKind::Bind, subflags, locator)
12163+
matchTypes(valueTy, boundValue, ConstraintKind::Bind, subflags,
12164+
locator.withPathElement(ConstraintLocator::KeyPathValue))
1215912165
.isFailure())
1216012166
return false;
1216112167

@@ -12409,8 +12415,8 @@ ConstraintSystem::simplifyKeyPathConstraint(
1240912415
} else {
1241012416
auto resolvedKPTy =
1241112417
BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
12412-
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
12413-
loc);
12418+
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind,
12419+
subflags, loc);
1241412420
}
1241512421
} else {
1241612422
formUnsolved();

test/Constraints/keypath.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,11 @@ func rdar32101765() {
255255
}
256256

257257
let _: KeyPath<R32101765, Float> = \.prop32101765
258-
// expected-error@-1 {{key path value type 'Int' cannot be converted to contextual type 'Float'}}
258+
// expected-error@-1 {{cannot assign value of type 'KeyPath<R32101765, Int>' to type 'KeyPath<R32101765, Float>'}}
259+
// expected-note@-2 {{arguments to generic parameter 'Value' ('Int' and 'Float') are expected to be equal}}
259260
let _: KeyPath<R32101765, Float> = \R32101765.prop32101765
260-
// expected-error@-1 {{key path value type 'Int' cannot be converted to contextual type 'Float'}}
261+
// expected-error@-1 {{cannot assign value of type 'KeyPath<R32101765, Int>' to type 'KeyPath<R32101765, Float>'}}
262+
// expected-note@-2 {{arguments to generic parameter 'Value' ('Int' and 'Float') are expected to be equal}}
261263
let _: KeyPath<R32101765, Float> = \.prop32101765.unknown
262264
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
263265
let _: KeyPath<R32101765, Float> = \R32101765.prop32101765.unknown

test/expr/unary/keypath/keypath.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -794,9 +794,11 @@ func test_keypath_with_method_refs() {
794794
}
795795

796796
let _: KeyPath<S, Int> = \.foo // expected-error {{key path cannot refer to instance method 'foo()'}}
797-
// expected-error@-1 {{key path value type '() -> Int' cannot be converted to contextual type 'Int'}}
797+
// expected-error@-1 {{cannot assign value of type 'KeyPath<S, () -> Int>' to type 'KeyPath<S, Int>'}}
798+
// expected-note@-2 {{arguments to generic parameter 'Value' ('() -> Int' and 'Int') are expected to be equal}}
798799
let _: KeyPath<S, Int> = \.bar // expected-error {{key path cannot refer to static method 'bar()'}}
799-
// expected-error@-1 {{key path value type '() -> Int' cannot be converted to contextual type 'Int'}}
800+
// expected-error@-1 {{cannot assign value of type 'KeyPath<S, () -> Int>' to type 'KeyPath<S, Int>'}}
801+
// expected-note@-2 {{arguments to generic parameter 'Value' ('() -> Int' and 'Int') are expected to be equal}}
800802
let _ = \S.Type.bar // expected-error {{key path cannot refer to static method 'bar()'}}
801803

802804
struct A {
@@ -1067,8 +1069,9 @@ func f_56996() {
10671069
// https://github.com/apple/swift/issues/55805
10681070
// Key-path missing optional crashes compiler: Inactive constraints left over?
10691071
func f_55805() {
1070-
let _: KeyPath<String?, Int?> = \.utf8.count // expected-error {{value of optional type 'String.UTF8View?' must be unwrapped to refer to member 'count' of wrapped base type 'String.UTF8View'}}
1071-
// expected-note@-1 {{chain the optional using '?' to access member 'count' only for non-'nil' base values}}
1072+
let _: KeyPath<String?, Int?> = \.utf8.count
1073+
// expected-error@-2 {{value of optional type 'String.UTF8View?' must be unwrapped to refer to member 'count' of wrapped base type 'String.UTF8View'}}
1074+
// expected-note@-3 {{chain the optional using '?' to access member 'count' only for non-'nil' base values}}
10721075
}
10731076

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

0 commit comments

Comments
 (0)