[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,
"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",
(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,
"key path must have at least one component", ())
ERROR(expr_string_interpolation_outside_string,none,

View File

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

View File

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

View File

@@ -230,11 +230,11 @@ func issue_65965() {
let refKP: ReferenceWritableKeyPath<S, String>
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>
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() {

View File

@@ -4,7 +4,7 @@ struct S {
let i: Int
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
// expected-error@-1 {{cannot assign through subscript: key path is read-only}}
@@ -12,7 +12,7 @@ struct S {
}
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
// 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 _: WritableKeyPath<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 _: PartialKeyPath<A> = \.[sub]
let _: KeyPath<A, A> = \.[sub]
let _: WritableKeyPath<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 _: PartialKeyPath<A> = \.optProperty?
@@ -162,7 +162,7 @@ func testKeyPath(sub: Sub, optSub: OptSub,
let _: KeyPath<C<A>, A> = \.value
let _: WritableKeyPath<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 _: PartialKeyPath<C<A>> = \C.value