Skip to content

Commit 9cbf165

Browse files
committed
Infer AsyncIteratorProtocol.Failure from next() throws.
When inferring the `Failure` associated type from the `next()` witness, account for the fact that it might itself use typed throws. Use the specified thrown error type for the inferred witness of `Failure`. Fixes rdar://125446918.
1 parent 07eb52a commit 9cbf165

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,13 +2426,17 @@ AssociatedTypeInference::computeFailureTypeWitness(
24262426
for (const auto &witness : valueWitnesses) {
24272427
if (isAsyncIteratorProtocolNext(witness.first)) {
24282428
if (auto witnessFunc = dyn_cast<AbstractFunctionDecl>(witness.second)) {
2429+
auto thrownError = witnessFunc->getEffectiveThrownErrorType();
2430+
24292431
// If it doesn't throw, Failure == Never.
2430-
if (!witnessFunc->hasThrows())
2432+
if (!thrownError)
24312433
return AbstractTypeWitness(assocType, ctx.getNeverType());
24322434

2433-
// If it isn't 'rethrows', Failure == any Error.
2434-
if (!witnessFunc->getAttrs().hasAttribute<RethrowsAttr>())
2435-
return AbstractTypeWitness(assocType, ctx.getErrorExistentialType());
2435+
// If it isn't 'rethrows', use the thrown error type;.
2436+
if (!witnessFunc->getAttrs().hasAttribute<RethrowsAttr>()) {
2437+
return AbstractTypeWitness(assocType,
2438+
dc->mapTypeIntoContext(*thrownError));
2439+
}
24362440

24372441
for (auto req : witnessFunc->getGenericSignature().getRequirements()) {
24382442
if (req.getKind() == RequirementKind::Conformance) {

test/Concurrency/async_sequence_rethrows.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,27 @@ extension InheritsAsyncSequence {
5151
try await self.reduce(into: [Element]()) { $0.append($1) }
5252
}
5353
}
54+
55+
// Ensure that we can get the thrown error type from next().
56+
struct Data { }
57+
58+
struct ErrorSequence<Element, Failure: Error>: AsyncSequence, AsyncIteratorProtocol {
59+
let throwError : Failure
60+
61+
func makeAsyncIterator() -> ErrorSequence<Element, Failure> {
62+
self
63+
}
64+
65+
mutating func next() async throws(Failure) -> Element? {
66+
throw throwError
67+
}
68+
}
69+
70+
enum MyError: Error {
71+
case foo
72+
}
73+
74+
75+
func getASequence() -> any AsyncSequence<Data, MyError> {
76+
return ErrorSequence<Data, _>(throwError: MyError.foo) // ERROR: Cannot convert return expression of type 'any Error' to return type 'MyError'
77+
}

0 commit comments

Comments
 (0)