[CSDiagnostics] Differentiate between key path type and value issues

Make sure that contextual mismatch uses a correct locator when
the issue is with key path value type instead of the key path
type.
This commit is contained in:
Pavel Yaskevich
2023-10-24 13:31:04 -07:00
parent bfeade4e39
commit 8b4985054a
6 changed files with 20 additions and 11 deletions

View File

@@ -678,9 +678,12 @@ ERROR(expr_swift_keypath_not_starting_with_type,none,
ERROR(expr_swift_keypath_not_starting_with_dot,none, ERROR(expr_swift_keypath_not_starting_with_dot,none,
"a Swift key path with contextual root must begin with a leading dot", "a Swift key path with contextual root must begin with a leading dot",
()) ())
ERROR(expr_smart_keypath_value_covert_to_contextual_type,none, ERROR(expr_keypath_value_covert_to_contextual_type,none,
"key path value type %0 cannot be converted to contextual type %1", "key path value type %0 cannot be converted to contextual type %1",
(Type, Type)) (Type, Type))
ERROR(expr_keypath_type_covert_to_contextual_type,none,
"cannot convert key path type %0 to contextual type %1",
(Type, Type))
ERROR(expr_swift_keypath_empty, none, ERROR(expr_swift_keypath_empty, none,
"key path must have at least one component", ()) "key path must have at least one component", ())
ERROR(expr_string_interpolation_outside_string,none, ERROR(expr_string_interpolation_outside_string,none,

View File

@@ -2497,7 +2497,7 @@ bool ContextualFailure::diagnoseAsError() {
if (path.empty()) { if (path.empty()) {
if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) { if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
emitDiagnosticAt(KPE->getLoc(), emitDiagnosticAt(KPE->getLoc(),
diag::expr_smart_keypath_value_covert_to_contextual_type, diag::expr_keypath_type_covert_to_contextual_type,
getFromType(), getToType()); getFromType(), getToType());
return true; return true;
} }
@@ -2744,6 +2744,11 @@ bool ContextualFailure::diagnoseAsError() {
break; break;
} }
case ConstraintLocator::KeyPathValue: {
diagnostic = diag::expr_keypath_value_covert_to_contextual_type;
break;
}
default: default:
return false; return false;
} }
@@ -7646,7 +7651,7 @@ bool ArgumentMismatchFailure::diagnoseKeyPathAsFunctionResultMismatch() const {
paramFnType->getParams().front().getPlainType()->isEqual(kpRootType))) paramFnType->getParams().front().getPlainType()->isEqual(kpRootType)))
return false; return false;
emitDiagnostic(diag::expr_smart_keypath_value_covert_to_contextual_type, emitDiagnostic(diag::expr_keypath_value_covert_to_contextual_type,
kpValueType, paramFnType->getResult()); kpValueType, paramFnType->getResult());
return true; return true;
} }

View File

@@ -6693,7 +6693,8 @@ bool ConstraintSystem::repairFailures(
} }
conversionsOrFixes.push_back(IgnoreContextualType::create( conversionsOrFixes.push_back(IgnoreContextualType::create(
*this, lhs, rhs, keyPathLoc)); *this, lhs, rhs,
getConstraintLocator(keyPathLoc, ConstraintLocator::KeyPathValue)));
break; break;
} }
default: default:

View File

@@ -230,11 +230,11 @@ func issue_65965() {
let refKP: ReferenceWritableKeyPath<S, String> let refKP: ReferenceWritableKeyPath<S, String>
refKP = \.s refKP = \.s
// expected-error@-1 {{key path value type 'WritableKeyPath<S, String>' cannot be converted to contextual type 'ReferenceWritableKeyPath<S, String>'}} // expected-error@-1 {{cannot convert key path type 'WritableKeyPath<S, String>' to contextual type 'ReferenceWritableKeyPath<S, String>'}}
let writeKP: WritableKeyPath<S, String> let writeKP: WritableKeyPath<S, String>
writeKP = \.v writeKP = \.v
// expected-error@-1 {{key path value type 'KeyPath<S, String>' cannot be converted to contextual type 'WritableKeyPath<S, String>'}} // expected-error@-1 {{cannot convert key path type 'KeyPath<S, String>' to contextual type 'WritableKeyPath<S, String>'}}
} }
func test_any_key_path() { func test_any_key_path() {

View File

@@ -4,7 +4,7 @@ struct S {
let i: Int let i: Int
init() { init() {
let _: WritableKeyPath<S, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<S, Int>' to specified type 'WritableKeyPath<S, Int>'}} let _: WritableKeyPath<S, Int> = \.i // expected-error {{cannot convert key path type 'KeyPath<S, Int>' to contextual type 'WritableKeyPath<S, Int>'}}
S()[keyPath: \.i] = 1 S()[keyPath: \.i] = 1
// expected-error@-1 {{cannot assign through subscript: key path is read-only}} // expected-error@-1 {{cannot assign through subscript: key path is read-only}}
@@ -12,7 +12,7 @@ struct S {
} }
func test() { func test() {
let _: WritableKeyPath<C, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<C, Int>' to specified type 'WritableKeyPath<C, Int>'}} let _: WritableKeyPath<C, Int> = \.i // expected-error {{cannot convert key path type 'KeyPath<C, Int>' to contextual type 'WritableKeyPath<C, Int>'}}
C()[keyPath: \.i] = 1 C()[keyPath: \.i] = 1
// expected-error@-1 {{cannot assign through subscript: key path is read-only}} // expected-error@-1 {{cannot assign through subscript: key path is read-only}}

View File

@@ -127,14 +127,14 @@ func testKeyPath(sub: Sub, optSub: OptSub,
let _: KeyPath<A, Prop> = \.property let _: KeyPath<A, Prop> = \.property
let _: WritableKeyPath<A, Prop> = \.property let _: WritableKeyPath<A, Prop> = \.property
let _: ReferenceWritableKeyPath<A, Prop> = \.property let _: ReferenceWritableKeyPath<A, Prop> = \.property
//expected-error@-1 {{cannot convert value of type 'WritableKeyPath<A, Prop>' to specified type 'ReferenceWritableKeyPath<A, Prop>'}} //expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, Prop>' to contextual type 'ReferenceWritableKeyPath<A, Prop>'}}
let _: (A) -> A = \.[sub] let _: (A) -> A = \.[sub]
let _: PartialKeyPath<A> = \.[sub] let _: PartialKeyPath<A> = \.[sub]
let _: KeyPath<A, A> = \.[sub] let _: KeyPath<A, A> = \.[sub]
let _: WritableKeyPath<A, A> = \.[sub] let _: WritableKeyPath<A, A> = \.[sub]
let _: ReferenceWritableKeyPath<A, A> = \.[sub] let _: ReferenceWritableKeyPath<A, A> = \.[sub]
//expected-error@-1 {{cannot convert value of type 'WritableKeyPath<A, A>' to specified type 'ReferenceWritableKeyPath<A, A>'}} //expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, A>' to contextual type 'ReferenceWritableKeyPath<A, A>'}}
let _: (A) -> Prop? = \.optProperty? let _: (A) -> Prop? = \.optProperty?
let _: PartialKeyPath<A> = \.optProperty? let _: PartialKeyPath<A> = \.optProperty?
@@ -162,7 +162,7 @@ func testKeyPath(sub: Sub, optSub: OptSub,
let _: KeyPath<C<A>, A> = \.value let _: KeyPath<C<A>, A> = \.value
let _: WritableKeyPath<C<A>, A> = \.value let _: WritableKeyPath<C<A>, A> = \.value
let _: ReferenceWritableKeyPath<C<A>, A> = \.value let _: ReferenceWritableKeyPath<C<A>, A> = \.value
// expected-error@-1 {{cannot convert value of type 'WritableKeyPath<C<A>, A>' to specified type 'ReferenceWritableKeyPath<C<A>, A>'}} // expected-error@-1 {{cannot convert key path type 'WritableKeyPath<C<A>, A>' to contextual type 'ReferenceWritableKeyPath<C<A>, A>'}}
let _: (C<A>) -> A = \C.value let _: (C<A>) -> A = \C.value
let _: PartialKeyPath<C<A>> = \C.value let _: PartialKeyPath<C<A>> = \C.value