Skip to content

[6.0] AsyncIteratorProtocol conformance fixes #72675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lib/Sema/AssociatedTypeInference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2426,13 +2426,17 @@ AssociatedTypeInference::computeFailureTypeWitness(
for (const auto &witness : valueWitnesses) {
if (isAsyncIteratorProtocolNext(witness.first)) {
if (auto witnessFunc = dyn_cast<AbstractFunctionDecl>(witness.second)) {
auto thrownError = witnessFunc->getEffectiveThrownErrorType();

// If it doesn't throw, Failure == Never.
if (!witnessFunc->hasThrows())
if (!thrownError)
return AbstractTypeWitness(assocType, ctx.getNeverType());

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

for (auto req : witnessFunc->getGenericSignature().getRequirements()) {
if (req.getKind() == RequirementKind::Conformance) {
Expand Down
17 changes: 15 additions & 2 deletions stdlib/public/Concurrency/AsyncIteratorProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ public protocol AsyncIteratorProtocol<Element, Failure> {

@available(SwiftStdlib 5.1, *)
extension AsyncIteratorProtocol {
/// Default implementation of `next()` in terms of `next()`, which is
/// required to maintain backward compatibility with existing async iterators.
/// Default implementation of `next(isolation:)` in terms of `next()`, which
/// is required to maintain backward compatibility with existing async
/// iterators.
@available(SwiftStdlib 6.0, *)
@inlinable
public mutating func next(isolation actor: isolated (any Actor)?) async throws(Failure) -> Element? {
Expand All @@ -123,3 +124,15 @@ extension AsyncIteratorProtocol {
}
}
}

@available(SwiftStdlib 5.1, *)
extension AsyncIteratorProtocol {
/// Default implementation of `next()` in terms of `next(isolation:)`, which
/// is required to maintain backward compatibility with existing async
/// iterators.
@available(SwiftStdlib 6.0, *)
@inlinable
public mutating func next() async throws(Failure) -> Element? {
return try await next(isolation: nil)
}
}
34 changes: 34 additions & 0 deletions test/Concurrency/async_sequence_rethrows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,37 @@ extension InheritsAsyncSequence {
try await self.reduce(into: [Element]()) { $0.append($1) }
}
}

// Ensure that we can get the thrown error type from next().
struct Data { }

struct ErrorSequence<Element, Failure: Error>: AsyncSequence, AsyncIteratorProtocol {
let throwError : Failure

func makeAsyncIterator() -> ErrorSequence<Element, Failure> {
self
}

mutating func next() async throws(Failure) -> Element? {
throw throwError
}
}

enum MyError: Error {
case foo
}


func getASequence() -> any AsyncSequence<Data, MyError> {
return ErrorSequence<Data, _>(throwError: MyError.foo) // ERROR: Cannot convert return expression of type 'any Error' to return type 'MyError'
}

// Test the default implementation of next() in terms of next(isolation:).
struct AsyncIteratorWithOnlyNextIsolation: AsyncIteratorProtocol {
public mutating func next(isolation: (any Actor)?) throws(MyError) -> Int? { 0 }
}

// Test the default implementation of next(isolation:) in terms of next().
struct AsyncIteratorWithOnlyNext: AsyncIteratorProtocol {
public mutating func next() throws(MyError) -> Int? { 0 }
}
8 changes: 7 additions & 1 deletion test/abi/macOS/arm64/concurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ Added: _$ss26withTaskExecutorPreference_9isolation9operationxSch_pSg_ScA_pSgYixy
// async function pointer to Swift.withTaskExecutorPreference<A, B where B: Swift.Error>(_: Swift.TaskExecutor?, isolation: isolated Swift.Actor?, operation: () async throws(B) -> A) async throws(B) -> A
Added: _$ss26withTaskExecutorPreference_9isolation9operationxSch_pSg_ScA_pSgYixyYaq_YKXEtYaq_YKs5ErrorR_r0_lFTu


// next() default implementation in terms of next(isolation:)
Added: _$sScIsE4next7ElementQzSgyYa7FailureQzYKF
Added: _$sScIsE4next7ElementQzSgyYa7FailureQzYKFTu

// === SerialExecutor.checkIsolated()
Added: _swift_task_checkIsolated
Added: _swift_task_checkIsolated_hook
Expand All @@ -284,4 +289,5 @@ Added: _$sScfsE13checkIsolatedyyF
// dispatch thunk of Swift.SerialExecutor.checkIsolated() -> ()
Added: _$sScf13checkIsolatedyyFTj
// method descriptor for Swift.SerialExecutor.checkIsolated() -> ()
Added: _$sScf13checkIsolatedyyFTq
Added: _$sScf13checkIsolatedyyFTq

8 changes: 7 additions & 1 deletion test/abi/macOS/x86_64/concurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ Added: _$ss26withTaskExecutorPreference_9isolation9operationxSch_pSg_ScA_pSgYixy
// async function pointer to Swift.withTaskExecutorPreference<A, B where B: Swift.Error>(_: Swift.TaskExecutor?, isolation: isolated Swift.Actor?, operation: () async throws(B) -> A) async throws(B) -> A
Added: _$ss26withTaskExecutorPreference_9isolation9operationxSch_pSg_ScA_pSgYixyYaq_YKXEtYaq_YKs5ErrorR_r0_lFTu


// next() default implementation in terms of next(isolation:)
Added: _$sScIsE4next7ElementQzSgyYa7FailureQzYKF
Added: _$sScIsE4next7ElementQzSgyYa7FailureQzYKFTu

// === SerialExecutor.checkIsolated()
Added: _swift_task_checkIsolated
Added: _swift_task_checkIsolated_hook
Expand All @@ -284,4 +289,5 @@ Added: _$sScfsE13checkIsolatedyyF
// dispatch thunk of Swift.SerialExecutor.checkIsolated() -> ()
Added: _$sScf13checkIsolatedyyFTj
// method descriptor for Swift.SerialExecutor.checkIsolated() -> ()
Added: _$sScf13checkIsolatedyyFTq
Added: _$sScf13checkIsolatedyyFTq