Skip to content

Commit 8b49850

Browse files
committed
[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.
1 parent bfeade4 commit 8b49850

File tree

6 files changed

+20
-11
lines changed

6 files changed

+20
-11
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,12 @@ ERROR(expr_swift_keypath_not_starting_with_type,none,
678678
ERROR(expr_swift_keypath_not_starting_with_dot,none,
679679
"a Swift key path with contextual root must begin with a leading dot",
680680
())
681-
ERROR(expr_smart_keypath_value_covert_to_contextual_type,none,
681+
ERROR(expr_keypath_value_covert_to_contextual_type,none,
682682
"key path value type %0 cannot be converted to contextual type %1",
683683
(Type, Type))
684+
ERROR(expr_keypath_type_covert_to_contextual_type,none,
685+
"cannot convert key path type %0 to contextual type %1",
686+
(Type, Type))
684687
ERROR(expr_swift_keypath_empty, none,
685688
"key path must have at least one component", ())
686689
ERROR(expr_string_interpolation_outside_string,none,

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,7 +2497,7 @@ bool ContextualFailure::diagnoseAsError() {
24972497
if (path.empty()) {
24982498
if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
24992499
emitDiagnosticAt(KPE->getLoc(),
2500-
diag::expr_smart_keypath_value_covert_to_contextual_type,
2500+
diag::expr_keypath_type_covert_to_contextual_type,
25012501
getFromType(), getToType());
25022502
return true;
25032503
}
@@ -2744,6 +2744,11 @@ bool ContextualFailure::diagnoseAsError() {
27442744
break;
27452745
}
27462746

2747+
case ConstraintLocator::KeyPathValue: {
2748+
diagnostic = diag::expr_keypath_value_covert_to_contextual_type;
2749+
break;
2750+
}
2751+
27472752
default:
27482753
return false;
27492754
}
@@ -7646,7 +7651,7 @@ bool ArgumentMismatchFailure::diagnoseKeyPathAsFunctionResultMismatch() const {
76467651
paramFnType->getParams().front().getPlainType()->isEqual(kpRootType)))
76477652
return false;
76487653

7649-
emitDiagnostic(diag::expr_smart_keypath_value_covert_to_contextual_type,
7654+
emitDiagnostic(diag::expr_keypath_value_covert_to_contextual_type,
76507655
kpValueType, paramFnType->getResult());
76517656
return true;
76527657
}

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6693,7 +6693,8 @@ bool ConstraintSystem::repairFailures(
66936693
}
66946694

66956695
conversionsOrFixes.push_back(IgnoreContextualType::create(
6696-
*this, lhs, rhs, keyPathLoc));
6696+
*this, lhs, rhs,
6697+
getConstraintLocator(keyPathLoc, ConstraintLocator::KeyPathValue)));
66976698
break;
66986699
}
66996700
default:

test/Constraints/keypath.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ func issue_65965() {
230230

231231
let refKP: ReferenceWritableKeyPath<S, String>
232232
refKP = \.s
233-
// expected-error@-1 {{key path value type 'WritableKeyPath<S, String>' cannot be converted to contextual type 'ReferenceWritableKeyPath<S, String>'}}
233+
// expected-error@-1 {{cannot convert key path type 'WritableKeyPath<S, String>' to contextual type 'ReferenceWritableKeyPath<S, String>'}}
234234

235235
let writeKP: WritableKeyPath<S, String>
236236
writeKP = \.v
237-
// expected-error@-1 {{key path value type 'KeyPath<S, String>' cannot be converted to contextual type 'WritableKeyPath<S, String>'}}
237+
// expected-error@-1 {{cannot convert key path type 'KeyPath<S, String>' to contextual type 'WritableKeyPath<S, String>'}}
238238
}
239239

240240
func test_any_key_path() {

test/Constraints/keypath_swift_5.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ struct S {
44
let i: Int
55

66
init() {
7-
let _: WritableKeyPath<S, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<S, Int>' to specified type 'WritableKeyPath<S, Int>'}}
7+
let _: WritableKeyPath<S, Int> = \.i // expected-error {{cannot convert key path type 'KeyPath<S, Int>' to contextual type 'WritableKeyPath<S, Int>'}}
88

99
S()[keyPath: \.i] = 1
1010
// expected-error@-1 {{cannot assign through subscript: key path is read-only}}
1111
}
1212
}
1313

1414
func test() {
15-
let _: WritableKeyPath<C, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<C, Int>' to specified type 'WritableKeyPath<C, Int>'}}
15+
let _: WritableKeyPath<C, Int> = \.i // expected-error {{cannot convert key path type 'KeyPath<C, Int>' to contextual type 'WritableKeyPath<C, Int>'}}
1616

1717
C()[keyPath: \.i] = 1
1818
// expected-error@-1 {{cannot assign through subscript: key path is read-only}}

test/expr/unary/keypath/keypath.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,14 @@ func testKeyPath(sub: Sub, optSub: OptSub,
127127
let _: KeyPath<A, Prop> = \.property
128128
let _: WritableKeyPath<A, Prop> = \.property
129129
let _: ReferenceWritableKeyPath<A, Prop> = \.property
130-
//expected-error@-1 {{cannot convert value of type 'WritableKeyPath<A, Prop>' to specified type 'ReferenceWritableKeyPath<A, Prop>'}}
130+
//expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, Prop>' to contextual type 'ReferenceWritableKeyPath<A, Prop>'}}
131131

132132
let _: (A) -> A = \.[sub]
133133
let _: PartialKeyPath<A> = \.[sub]
134134
let _: KeyPath<A, A> = \.[sub]
135135
let _: WritableKeyPath<A, A> = \.[sub]
136136
let _: ReferenceWritableKeyPath<A, A> = \.[sub]
137-
//expected-error@-1 {{cannot convert value of type 'WritableKeyPath<A, A>' to specified type 'ReferenceWritableKeyPath<A, A>'}}
137+
//expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, A>' to contextual type 'ReferenceWritableKeyPath<A, A>'}}
138138

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

167167
let _: (C<A>) -> A = \C.value
168168
let _: PartialKeyPath<C<A>> = \C.value

0 commit comments

Comments
 (0)