Skip to content

Commit ff45fec

Browse files
committed
[Typed throws] Handle key-path literal used with a function that has typed throws
When providing a key-path literal for a parameter of function type where that function type has a generic parameter for its thrown error type, infer `Never` for the generic argument because key paths don't throw. Thanks to @xedin for realizing that this would be an issue.
1 parent a67b818 commit ff45fec

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12248,6 +12248,16 @@ ConstraintSystem::simplifyKeyPathConstraint(
1224812248
// { root in root[keyPath: kp] }.
1224912249
boundRoot = fnTy->getParams()[0].getParameterType();
1225012250
boundValue = fnTy->getResult();
12251+
12252+
// Key paths never throw, so if the function has a thrown error type
12253+
// that is a type variable, infer it to be Never.
12254+
if (auto thrownError = fnTy->getThrownError()) {
12255+
if (thrownError->isTypeVariableOrMember()) {
12256+
(void)matchTypes(
12257+
thrownError, getASTContext().getNeverType(),
12258+
ConstraintKind::Equal, TMF_GenerateConstraints, locator);
12259+
}
12260+
}
1225112261
}
1225212262

1225312263
if (boundRoot &&

test/decl/func/typed_throws.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,14 @@ func mapArray<T, U, E: Error>(_ array: [T], body: (T) throws(E) -> U) throws(E)
7676
return resultArray
7777
}
7878

79+
struct Person {
80+
var name: String
81+
}
82+
7983
func addOrThrowUntyped(_ i: Int, _ j: Int) throws -> Int { i + j }
8084
func addOrThrowMyError(_ i: Int, _ j: Int) throws(MyError) -> Int { i + j }
8185

82-
func testMapArray(numbers: [Int]) {
86+
func testMapArray(numbers: [Int], friends: [Person]) {
8387
// Note: try is not required, because this throws Never
8488
_ = mapArray(numbers) { $0 + 1 }
8589

@@ -101,6 +105,11 @@ func testMapArray(numbers: [Int]) {
101105
} catch {
102106
let _: Int = error // expected-error{{cannot convert value of type 'MyError' to specified type 'Int'}}
103107
}
108+
109+
do {
110+
// Keypath-as-function
111+
_ = mapArray(friends, body: \Person.name)
112+
}
104113
}
105114

106115
// Inference of Error conformance from the use of a generic parameter in typed

0 commit comments

Comments
 (0)