Skip to content

Commit cceef44

Browse files
committed
[CSSimplify] Detect and diagnose invalid arguments for key path subscript
1 parent 32a7afc commit cceef44

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

lib/Sema/CSSimplify.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -12415,8 +12415,17 @@ ConstraintSystem::simplifyKeyPathApplicationConstraint(
1241512415
// Otherwise, we don't have a key path type at all.
1241612416
return SolutionKind::Error;
1241712417
}
12418-
if (!keyPathTy->isTypeVariableOrMember())
12418+
12419+
if (!keyPathTy->isTypeVariableOrMember()) {
12420+
if (shouldAttemptFixes()) {
12421+
auto *fix = IgnoreKeyPathSubscriptIndexMismatch::create(
12422+
*this, keyPathTy, getConstraintLocator(locator));
12423+
recordAnyTypeVarAsPotentialHole(valueTy);
12424+
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
12425+
}
12426+
1241912427
return SolutionKind::Error;
12428+
}
1242012429

1242112430
return unsolved();
1242212431
}

test/Constraints/keypath.swift

+39
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,42 @@ func rdar32101765() {
265265
let _: KeyPath<R32101765, Float> = \R32101765.prop32101765.unknown
266266
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
267267
}
268+
269+
// https://github.com/apple/swift/issues/69795
270+
func test_invalid_argument_to_keypath_subscript() {
271+
func test(x: Int) {
272+
x[keyPath: 5]
273+
// expected-error@-1 {{cannot use value of type 'Int' as a key path subscript index; argument must be a key path}}
274+
}
275+
276+
let _: (Int) -> Void = {
277+
let y = $0
278+
y[keyPath: 5]
279+
// expected-error@-1 {{cannot use value of type 'Int' as a key path subscript index; argument must be a key path}}
280+
}
281+
282+
func ambiguous(_: (String) -> Void) {}
283+
func ambiguous(_: (Int) -> Void) {}
284+
285+
// FIXME(diagnostic): This is not properly diagnosed in a general case and key path application is even more
286+
// complicated because overloads anchored on 'SubscriptExpr -> subscript member' do not point to declarations.
287+
// The diagnostic should point out that `ambiguous` is indeed ambiguous and that `5` is not a valid argument
288+
// for a key path subscript.
289+
ambiguous {
290+
// expected-error@-1 {{type of expression is ambiguous without a type annotation}}
291+
$0[keyPath: 5]
292+
}
293+
294+
class A {
295+
}
296+
297+
func test_invalid_existential_protocol(base: String, v: any BinaryInteger) {
298+
base[keyPath: v]
299+
// expected-error@-1 {{cannot use value of type 'any BinaryInteger' as a key path subscript index; argument must be a key path}}
300+
}
301+
302+
func test_invalid_existential_composition(base: String, v: any A & BinaryInteger) {
303+
base[keyPath: v]
304+
// expected-error@-1 {{cannot use value of type 'A' as a key path subscript index; argument must be a key path}}
305+
}
306+
}

0 commit comments

Comments
 (0)