Skip to content

Commit b1ccdc3

Browse files
committed
[CSSimplify] Match root/value of a key path even when superclass check fails
This helps to propagate types bi-directionally and avoid extraneous failures related to generic parameter inference when the real issue is mutability or type erasure.
1 parent 270bbc5 commit b1ccdc3

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14920,7 +14920,31 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
1492014920
}
1492114921

1492214922
assert(fix);
14923-
return !recordFix(fix, impact);
14923+
14924+
if (recordFix(fix, impact))
14925+
return false;
14926+
14927+
// If we are trying to check whether "from" key path is a subclass of
14928+
// of a "to" key path, the problem here is either mutablity or erasure
14929+
// and we should still try to match their root and value types top help
14930+
// inference.
14931+
if (restriction == ConversionRestrictionKind::Superclass) {
14932+
if (fromType->isKnownKeyPathType() && toType->isKnownKeyPathType() &&
14933+
!fromType->isAnyKeyPath()) {
14934+
auto fromKeyPath = fromType->castTo<BoundGenericType>();
14935+
auto toKeyPath = toType->castTo<BoundGenericType>();
14936+
14937+
auto flags = subflags;
14938+
flags |= TMF_ApplyingFix;
14939+
flags |= TMF_MatchingGenericArguments;
14940+
14941+
(void)matchDeepTypeArguments(*this, flags,
14942+
fromKeyPath->getGenericArgs(),
14943+
toKeyPath->getGenericArgs(), locator);
14944+
}
14945+
}
14946+
14947+
return true;
1492414948
}
1492514949

1492614950
return false;

test/Availability/availability_accessors.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,14 +579,11 @@ func testKeyPathArguments_Struct() {
579579
takesSendableKeyPath(x, \.deprecatedSetter)
580580

581581
func takesWritableKeyPath<T, U>(_ t: inout T, _ keyPath: WritableKeyPath<T, U>) -> () { }
582-
// expected-note@-1 2 {{in call to function 'takesWritableKeyPath'}}
583582

584583
takesWritableKeyPath(&x, \.available)
585584
takesWritableKeyPath(&x, \.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
586585
takesWritableKeyPath(&x, \.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
587-
// expected-error@-1 {{generic parameter 'U' could not be inferred}}
588586
takesWritableKeyPath(&x, \.unavailableGetterAndSetter) // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
589-
// expected-error@-1 {{generic parameter 'U' could not be inferred}}
590587
takesWritableKeyPath(&x, \.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
591588
takesWritableKeyPath(&x, \.deprecatedSetter) // expected-warning {{setter for 'deprecatedSetter' is deprecated: writing not recommended}}
592589

test/stdlib/KeyPathAppending.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func mismatchedAppends<T, U, V>(readOnlyLeft: KeyPath<T, U>,
6161
// expected-error@-1 {{no exact matches in call to instance method 'appending'}}
6262

6363
_ = writableRight.appending(path: readOnlyLeft)
64-
// expected-error@-1 {{instance method 'appending(path:)' requires that 'KeyPath<U, V>' inherit from 'KeyPath<U, T>'}}
64+
// expected-error@-1 {{no exact matches in call to instance method 'appending'}}
6565

6666
_ = writableRight.appending(path: writableLeft)
6767
// expected-error@-1 {{cannot convert value of type 'WritableKeyPath<T, U>' to expected argument type 'WritableKeyPath<V, U>'}}
@@ -71,7 +71,7 @@ func mismatchedAppends<T, U, V>(readOnlyLeft: KeyPath<T, U>,
7171
// expected-error@-1 {{no exact matches in call to instance method 'appending'}}
7272

7373
_ = referenceRight.appending(path: readOnlyLeft)
74-
// expected-error@-1 {{instance method 'appending(path:)' requires that 'KeyPath<U, V>' inherit from 'KeyPath<U, T>'}}
74+
// expected-error@-1 {{no exact matches in call to instance method 'appending'}}
7575

7676
_ = referenceRight.appending(path: writableLeft)
7777
// expected-error@-1 {{cannot convert value of type 'WritableKeyPath<T, U>' to expected argument type 'WritableKeyPath<V, U>'}}

0 commit comments

Comments
 (0)