From 8b4985054a4b35c89e40b3e44a73db73ffc40305 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 24 Oct 2023 13:31:04 -0700 Subject: [PATCH] [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. --- include/swift/AST/DiagnosticsSema.def | 5 ++++- lib/Sema/CSDiagnostics.cpp | 9 +++++++-- lib/Sema/CSSimplify.cpp | 3 ++- test/Constraints/keypath.swift | 4 ++-- test/Constraints/keypath_swift_5.swift | 4 ++-- test/expr/unary/keypath/keypath.swift | 6 +++--- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index bf7f746e8fb..ff426c6058e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -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, diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 38b9dc5bc36..fec8ad73daf 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2497,7 +2497,7 @@ bool ContextualFailure::diagnoseAsError() { if (path.empty()) { if (auto *KPE = getAsExpr(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; } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index da37eb38ac3..cedeaba183b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -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: diff --git a/test/Constraints/keypath.swift b/test/Constraints/keypath.swift index 43c387afd95..ea757215221 100644 --- a/test/Constraints/keypath.swift +++ b/test/Constraints/keypath.swift @@ -230,11 +230,11 @@ func issue_65965() { let refKP: ReferenceWritableKeyPath refKP = \.s - // expected-error@-1 {{key path value type 'WritableKeyPath' cannot be converted to contextual type 'ReferenceWritableKeyPath'}} + // expected-error@-1 {{cannot convert key path type 'WritableKeyPath' to contextual type 'ReferenceWritableKeyPath'}} let writeKP: WritableKeyPath writeKP = \.v - // expected-error@-1 {{key path value type 'KeyPath' cannot be converted to contextual type 'WritableKeyPath'}} + // expected-error@-1 {{cannot convert key path type 'KeyPath' to contextual type 'WritableKeyPath'}} } func test_any_key_path() { diff --git a/test/Constraints/keypath_swift_5.swift b/test/Constraints/keypath_swift_5.swift index 30cc8aa523b..4883dc6b3c9 100644 --- a/test/Constraints/keypath_swift_5.swift +++ b/test/Constraints/keypath_swift_5.swift @@ -4,7 +4,7 @@ struct S { let i: Int init() { - let _: WritableKeyPath = \.i // expected-error {{cannot convert value of type 'KeyPath' to specified type 'WritableKeyPath'}} + let _: WritableKeyPath = \.i // expected-error {{cannot convert key path type 'KeyPath' to contextual type 'WritableKeyPath'}} 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 = \.i // expected-error {{cannot convert value of type 'KeyPath' to specified type 'WritableKeyPath'}} + let _: WritableKeyPath = \.i // expected-error {{cannot convert key path type 'KeyPath' to contextual type 'WritableKeyPath'}} C()[keyPath: \.i] = 1 // expected-error@-1 {{cannot assign through subscript: key path is read-only}} diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift index a5f12f29df0..e1169339647 100644 --- a/test/expr/unary/keypath/keypath.swift +++ b/test/expr/unary/keypath/keypath.swift @@ -127,14 +127,14 @@ func testKeyPath(sub: Sub, optSub: OptSub, let _: KeyPath = \.property let _: WritableKeyPath = \.property let _: ReferenceWritableKeyPath = \.property - //expected-error@-1 {{cannot convert value of type 'WritableKeyPath' to specified type 'ReferenceWritableKeyPath'}} + //expected-error@-1 {{cannot convert key path type 'WritableKeyPath' to contextual type 'ReferenceWritableKeyPath'}} let _: (A) -> A = \.[sub] let _: PartialKeyPath = \.[sub] let _: KeyPath = \.[sub] let _: WritableKeyPath = \.[sub] let _: ReferenceWritableKeyPath = \.[sub] - //expected-error@-1 {{cannot convert value of type 'WritableKeyPath' to specified type 'ReferenceWritableKeyPath'}} + //expected-error@-1 {{cannot convert key path type 'WritableKeyPath' to contextual type 'ReferenceWritableKeyPath'}} let _: (A) -> Prop? = \.optProperty? let _: PartialKeyPath = \.optProperty? @@ -162,7 +162,7 @@ func testKeyPath(sub: Sub, optSub: OptSub, let _: KeyPath, A> = \.value let _: WritableKeyPath, A> = \.value let _: ReferenceWritableKeyPath, A> = \.value - // expected-error@-1 {{cannot convert value of type 'WritableKeyPath, A>' to specified type 'ReferenceWritableKeyPath, A>'}} + // expected-error@-1 {{cannot convert key path type 'WritableKeyPath, A>' to contextual type 'ReferenceWritableKeyPath, A>'}} let _: (C) -> A = \C.value let _: PartialKeyPath> = \C.value