Skip to content

Commit 0514925

Browse files
authored
Merge pull request #69465 from DougGregor/typed-throws-fixes
[Typed throws] Additional fixes for typed throws
2 parents b99a4f8 + d3ede19 commit 0514925

File tree

4 files changed

+39
-8
lines changed

4 files changed

+39
-8
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,11 @@ InferredGenericSignatureRequest::evaluate(
849849
// Finish by adding any remaining requirements. This is used to introduce
850850
// inferred same-type requirements when building the generic signature of
851851
// an extension whose extended type is a generic typealias.
852+
SmallVector<Requirement, 4> rawAddedRequirements;
852853
for (const auto &req : addedRequirements)
853-
requirements.push_back({req, SourceLoc(), /*wasInferred=*/true});
854+
desugarRequirement(req, SourceLoc(), rawAddedRequirements, errors);
855+
for (const auto &req : rawAddedRequirements)
856+
requirements.push_back({req, SourceLoc(), /*inferred=*/true});
854857

855858
// Re-order requirements so that inferred requirements appear last. This
856859
// ensures that if an inferred requirement is redundant with some other

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 &&

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -768,12 +768,10 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
768768
inferenceSources.emplace_back(thrownTypeRepr, thrownType);
769769

770770
// Add conformance of this type to the Error protocol.
771-
if (thrownType->isTypeParameter()) {
772-
if (auto errorProtocol = ctx.getErrorDecl()) {
773-
extraReqs.push_back(
774-
Requirement(RequirementKind::Conformance, thrownType,
775-
errorProtocol->getDeclaredInterfaceType()));
776-
}
771+
if (auto errorProtocol = ctx.getErrorDecl()) {
772+
extraReqs.push_back(
773+
Requirement(RequirementKind::Conformance, thrownType,
774+
errorProtocol->getDeclaredInterfaceType()));
777775
}
778776
}
779777
}

test/decl/func/typed_throws.swift

Lines changed: 21 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
@@ -126,3 +135,14 @@ struct HasASubscript {
126135

127136
// expected-error@+1{{thrown type 'any Codable & Error' (aka 'any Decodable & Encodable & Error') does not conform to the 'Error' protocol}}
128137
func throwCodableErrors() throws(any Codable & Error) { }
138+
139+
enum Either<First, Second> {
140+
case first(First)
141+
case second(Second)
142+
}
143+
144+
extension Either: Error where First: Error, Second: Error { }
145+
146+
func f<E1, E2>(_ error: Either<E1, E2>) throws(Either<E1, E2>) {
147+
throw error
148+
}

0 commit comments

Comments
 (0)