From 860b8cdf488cd3958a4be447297e13327b17956b Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 8 May 2023 14:18:11 -0700 Subject: [PATCH] Concurrency: Revert workarounds for `@backDeployed` condfails. All compilers that must be able to compile the standard library's textual interface accept the following: - back deployed functions declared without `@available` - `@inlinable` back deployed functions - `defer` blocks in back deployed functions We can therefore revert the workarounds added in https://github.com/apple/swift/pull/62946/ and https://github.com/apple/swift/pull/62928/. Resolves rdar://104085810 --- .../BackDeployConcurrency/TaskCancellation.swift | 13 ++++--------- stdlib/public/BackDeployConcurrency/TaskLocal.swift | 7 +++---- stdlib/public/Concurrency/TaskCancellation.swift | 13 ++++--------- stdlib/public/Concurrency/TaskLocal.swift | 7 +++---- test/api-digester/stability-concurrency-abi.test | 6 ++++-- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/stdlib/public/BackDeployConcurrency/TaskCancellation.swift b/stdlib/public/BackDeployConcurrency/TaskCancellation.swift index a504dbeb0110a..dcbd3184b5201 100644 --- a/stdlib/public/BackDeployConcurrency/TaskCancellation.swift +++ b/stdlib/public/BackDeployConcurrency/TaskCancellation.swift @@ -38,7 +38,7 @@ import Swift /// the operation gets to run. @_unsafeInheritExecutor // the operation runs on the same executor as we start out with @available(SwiftStdlib 5.1, *) -@_backDeploy(before: SwiftStdlib 5.8) +@backDeployed(before: SwiftStdlib 5.8) public func withTaskCancellationHandler( operation: () async throws -> T, onCancel handler: @Sendable () -> Void @@ -46,14 +46,9 @@ public func withTaskCancellationHandler( // unconditionally add the cancellation record to the task. // if the task was already cancelled, it will be executed right away. let record = _taskAddCancellationHandler(handler: handler) - do { - let result = try await operation() - _taskRemoveCancellationHandler(record: record) - return result - } catch { - _taskRemoveCancellationHandler(record: record) - throw error - } + defer { _taskRemoveCancellationHandler(record: record) } + + return try await operation() } @available(SwiftStdlib 5.1, *) diff --git a/stdlib/public/BackDeployConcurrency/TaskLocal.swift b/stdlib/public/BackDeployConcurrency/TaskLocal.swift index 7b5b44e88c4b0..94d470883e4af 100644 --- a/stdlib/public/BackDeployConcurrency/TaskLocal.swift +++ b/stdlib/public/BackDeployConcurrency/TaskLocal.swift @@ -135,10 +135,10 @@ public final class TaskLocal: Sendable, CustomStringConvertible /// /// If the value is a reference type, it will be retained for the duration of /// the operation closure. + @inlinable @discardableResult @_unsafeInheritExecutor - @available(SwiftStdlib 5.1, *) // back deploy requires we declare the availability explicitly on this method - @_backDeploy(before: SwiftStdlib 5.8) + @backDeployed(before: SwiftStdlib 5.8) public func withValue(_ valueDuringOperation: Value, operation: () async throws -> R, file: String = #file, line: UInt = #line) async rethrows -> R { return try await withValueImpl(valueDuringOperation, operation: operation, file: file, line: line) @@ -165,8 +165,7 @@ public final class TaskLocal: Sendable, CustomStringConvertible @inlinable @discardableResult @_unsafeInheritExecutor - @available(SwiftStdlib 5.1, *) // back deploy requires we declare the availability explicitly on this method - @_backDeploy(before: SwiftStdlib 5.9) + @backDeployed(before: SwiftStdlib 5.9) internal func withValueImpl(_ valueDuringOperation: __owned Value, operation: () async throws -> R, file: String = #fileID, line: UInt = #line) async rethrows -> R { // check if we're not trying to bind a value from an illegal context; this may crash diff --git a/stdlib/public/Concurrency/TaskCancellation.swift b/stdlib/public/Concurrency/TaskCancellation.swift index a504dbeb0110a..dcbd3184b5201 100644 --- a/stdlib/public/Concurrency/TaskCancellation.swift +++ b/stdlib/public/Concurrency/TaskCancellation.swift @@ -38,7 +38,7 @@ import Swift /// the operation gets to run. @_unsafeInheritExecutor // the operation runs on the same executor as we start out with @available(SwiftStdlib 5.1, *) -@_backDeploy(before: SwiftStdlib 5.8) +@backDeployed(before: SwiftStdlib 5.8) public func withTaskCancellationHandler( operation: () async throws -> T, onCancel handler: @Sendable () -> Void @@ -46,14 +46,9 @@ public func withTaskCancellationHandler( // unconditionally add the cancellation record to the task. // if the task was already cancelled, it will be executed right away. let record = _taskAddCancellationHandler(handler: handler) - do { - let result = try await operation() - _taskRemoveCancellationHandler(record: record) - return result - } catch { - _taskRemoveCancellationHandler(record: record) - throw error - } + defer { _taskRemoveCancellationHandler(record: record) } + + return try await operation() } @available(SwiftStdlib 5.1, *) diff --git a/stdlib/public/Concurrency/TaskLocal.swift b/stdlib/public/Concurrency/TaskLocal.swift index 170839d4954c5..8d2dad2943c5e 100644 --- a/stdlib/public/Concurrency/TaskLocal.swift +++ b/stdlib/public/Concurrency/TaskLocal.swift @@ -135,10 +135,10 @@ public final class TaskLocal: Sendable, CustomStringConvertible /// /// If the value is a reference type, it will be retained for the duration of /// the operation closure. + @inlinable @discardableResult @_unsafeInheritExecutor - @available(SwiftStdlib 5.1, *) // back deploy requires we declare the availability explicitly on this method - @_backDeploy(before: SwiftStdlib 5.8) + @backDeployed(before: SwiftStdlib 5.8) public func withValue(_ valueDuringOperation: Value, operation: () async throws -> R, file: String = #fileID, line: UInt = #line) async rethrows -> R { return try await withValueImpl(valueDuringOperation, operation: operation, file: file, line: line) @@ -165,8 +165,7 @@ public final class TaskLocal: Sendable, CustomStringConvertible @inlinable @discardableResult @_unsafeInheritExecutor - @available(SwiftStdlib 5.1, *) // back deploy requires we declare the availability explicitly on this method - @_backDeploy(before: SwiftStdlib 5.9) + @backDeployed(before: SwiftStdlib 5.9) internal func withValueImpl(_ valueDuringOperation: __owned Value, operation: () async throws -> R, file: String = #fileID, line: UInt = #line) async rethrows -> R { // check if we're not trying to bind a value from an illegal context; this may crash diff --git a/test/api-digester/stability-concurrency-abi.test b/test/api-digester/stability-concurrency-abi.test index 86047608f6590..ee13178ddafae 100644 --- a/test/api-digester/stability-concurrency-abi.test +++ b/test/api-digester/stability-concurrency-abi.test @@ -31,8 +31,7 @@ // false positives, or if you have special permission to break things.) You can // find a diff of what needs to be added in the output of the failed test run. // The order of lines doesn't matter, and you can also include comments to refer -// to any bugs you filed. Remember that in almost all cases you'll want to edit -// the stability-stdlib-abi-without-asserts.test file instead of this one. +// to any bugs you filed. // // Thank you for your help ensuring the stdlib remains compatible with its past! // -- Your friendly stdlib engineers @@ -72,4 +71,7 @@ Func SerialExecutor.enqueue(_:) has been added as a protocol requirement // rdar://106833284 (ABI checker confused with overload getting deprecated) Func Executor.enqueue(_:) is a new API without @available attribute +// This function correctly inherits its availability from the TaskLocal struct. +Func TaskLocal.withValueImpl(_:operation:file:line:) is a new API without @available attribute + // *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)