Skip to content

Commit ed8e82d

Browse files
committed
Adopt @abi in the standard library
This commit enables the ABIAttribute feature in the standard library build and replaces (nearly) every instance of `@_silgen_name(<mangled Swift name>)` in stdlib/public with an `@abi` attribute.
1 parent 4bf217f commit ed8e82d

36 files changed

+465
-189
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -1131,15 +1131,17 @@ ways to misuse it:
11311131
be reliably recovered through C interfaces like `dlsym`. If you want to
11321132
implement a plugin-style interface, use `Bundle`/`NSBundle` if available, or
11331133
export your plugin entry points as C entry points using `@_cdecl`.
1134-
1134+
- Don't use `@_silgen_name` when you need to make a change to an ABI-stable
1135+
declaration's signature that would normally alter its mangled name, but you
1136+
need to preserve the old mangled name for ABI compatibility. We used to use it
1137+
for this task, but `@abi` can do it with fewer limitations, more safety, and
1138+
better readability. If for some reason you do need `@_silgen_name`, you will
1139+
need to be careful that the change doesn't materially affect the actual
1140+
calling convention of the function in an incompatible way.
1141+
11351142
Legitimate uses may include:
11361143

11371144
- Use `@_silgen_name` if you're implementing the Swift runtime.
1138-
- Use `@_silgen_name` if you need to make a change to an ABI-stable
1139-
declaration's signature that would normally alter its mangled name, but you
1140-
need to preserve the old mangled name for ABI compatibility. You will need
1141-
to be careful that the change doesn't materially affect the actual calling
1142-
convention of the function in an incompatible way.
11431145
- Use `@_silgen_name` if certain declarations need to have predictable symbol
11441146
names, such as to be easily referenced by linker scripts or other highly
11451147
customized build environments (and it's OK for those predictable symbols to

docs/StandardLibraryProgrammersManual.md

+2
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ This attribute specifies the name that a declaration will have at link time. It
455455
1. To specify the symbol name of a Swift function so that it can be called from Swift-aware C. Such functions have bodies.
456456
2. To provide a Swift declaration which really represents a C declaration. Such functions do not have bodies.
457457
458+
In the past it was sometimes used for ABI backwards compatibility hacks, but `@abi` does this job better.
459+
458460
##### Using `@_silgen_name` to call Swift from Swift-aware C
459461
460462
Rather than hard-code Swift mangling into C code, `@_silgen_name` is used to provide a stable and known symbol name for linking. Note that C code still must understand and use the Swift calling convention (available in swift-clang) for such Swift functions (if they use Swift's CC). Example:

stdlib/cmake/modules/SwiftSource.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ function(_compile_swift_files
631631

632632
list(APPEND swift_flags "-enable-experimental-feature" "NonescapableTypes")
633633
list(APPEND swift_flags "-enable-experimental-feature" "LifetimeDependence")
634+
list(APPEND swift_flags "-enable-experimental-feature" "ABIAttribute")
634635

635636
list(APPEND swift_flags "-enable-upcoming-feature" "MemberImportVisibility")
636637

stdlib/public/Concurrency/AsyncStream.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,12 @@ public struct AsyncStream<Element> {
330330
/// }
331331
///
332332
///
333-
@_silgen_name("$sScS9unfolding8onCancelScSyxGxSgyYac_yyYbcSgtcfC")
333+
@abi(
334+
init(
335+
unfolding produce: @escaping /* not @Sendable*/ () async -> Element?,
336+
onCancel: (@Sendable () -> Void)?
337+
)
338+
)
334339
@preconcurrency // Original API had `@Sendable` only on `onCancel`
335340
public init(
336341
unfolding produce: @escaping @Sendable () async -> Element?,

stdlib/public/Concurrency/CheckedContinuation.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,14 @@ public func withCheckedContinuation<T>(
313313
//
314314
// This function also doubles as an ABI-compatibility shim predating the
315315
// introduction of #isolation.
316+
@abi(
317+
func withCheckedContinuation<T>(
318+
function: String,
319+
_ body: (CheckedContinuation<T, Never>) -> Void
320+
) async -> T
321+
)
316322
@available(SwiftStdlib 5.1, *)
317323
@_unsafeInheritExecutor // ABI compatibility with Swift 5.1
318-
@_silgen_name("$ss23withCheckedContinuation8function_xSS_yScCyxs5NeverOGXEtYalF")
319324
public func _unsafeInheritExecutor_withCheckedContinuation<T>(
320325
function: String = #function,
321326
_ body: (CheckedContinuation<T, Never>) -> Void
@@ -377,9 +382,14 @@ public func withCheckedThrowingContinuation<T>(
377382
//
378383
// This function also doubles as an ABI-compatibility shim predating the
379384
// introduction of #isolation.
385+
@abi(
386+
func withCheckedThrowingContinuation<T>(
387+
function: String,
388+
_ body: (CheckedContinuation<T, Error>) -> Void
389+
) async throws -> T
390+
)
380391
@available(SwiftStdlib 5.1, *)
381392
@_unsafeInheritExecutor // ABI compatibility with Swift 5.1
382-
@_silgen_name("$ss31withCheckedThrowingContinuation8function_xSS_yScCyxs5Error_pGXEtYaKlF")
383393
public func _unsafeInheritExecutor_withCheckedThrowingContinuation<T>(
384394
function: String = #function,
385395
_ body: (CheckedContinuation<T, Error>) -> Void

stdlib/public/Concurrency/DiscardingTaskGroup.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,14 @@ public func withDiscardingTaskGroup<GroupResult>(
9797
//
9898
// This function also doubles as an ABI-compatibility shim predating the
9999
// introduction of #isolation.
100+
@abi(
101+
func withDiscardingTaskGroup<GroupResult>(
102+
returning returnType: GroupResult.Type,
103+
body: (inout DiscardingTaskGroup) async -> GroupResult
104+
) async -> GroupResult
105+
)
100106
@available(SwiftStdlib 5.9, *)
101107
@_unsafeInheritExecutor // for ABI compatibility
102-
@_silgen_name("$ss23withDiscardingTaskGroup9returning4bodyxxm_xs0bcD0VzYaXEtYalF")
103108
public func _unsafeInheritExecutor_withDiscardingTaskGroup<GroupResult>(
104109
returning returnType: GroupResult.Type = GroupResult.self,
105110
body: (inout DiscardingTaskGroup) async -> GroupResult
@@ -367,9 +372,14 @@ public func withThrowingDiscardingTaskGroup<GroupResult>(
367372
return result
368373
}
369374

375+
@abi(
376+
func withThrowingDiscardingTaskGroup<GroupResult>(
377+
returning returnType: GroupResult.Type,
378+
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult
379+
) async throws -> GroupResult
380+
)
370381
@available(SwiftStdlib 5.9, *)
371382
@_unsafeInheritExecutor // for ABI compatibility
372-
@_silgen_name("$ss31withThrowingDiscardingTaskGroup9returning4bodyxxm_xs0bcdE0Vys5Error_pGzYaKXEtYaKlF")
373383
public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
374384
returning returnType: GroupResult.Type = GroupResult.self,
375385
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult

stdlib/public/Concurrency/ExecutorAssertions.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,16 @@ extension Actor {
368368
}
369369
}
370370

371+
@abi(
372+
nonisolated func assumeIsolated<T /* not ': Sendable' */>(
373+
_ operation: (isolated Self) throws -> T,
374+
file: StaticString, line: UInt
375+
) rethrows -> T
376+
)
371377
@available(SwiftStdlib 5.9, *)
372378
@usableFromInline
373379
@_unavailableInEmbedded
374-
@_silgen_name("$sScAsE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKlF")
375-
internal nonisolated func __abi__assumeIsolated<T : Sendable>(
380+
internal nonisolated func __nonsendable_assumeIsolated<T : Sendable>(
376381
_ operation: (isolated Self) throws -> T,
377382
_ file: StaticString, _ line: UInt
378383
) rethrows -> T {

stdlib/public/Concurrency/MainActor.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,15 @@ extension MainActor {
148148
}
149149
}
150150

151+
@abi(
152+
static func assumeIsolated<T /* not ': Sendable' */>(
153+
_ operation: @MainActor () throws -> T,
154+
file: StaticString, line: UInt
155+
) rethrows -> T
156+
)
151157
@available(SwiftStdlib 5.9, *)
152158
@usableFromInline
153-
@_silgen_name("$sScM14assumeIsolated_4file4linexxyKScMYcXE_s12StaticStringVSutKlFZ")
154-
internal static func __abi__assumeIsolated<T : Sendable>(
159+
internal static func __nonsendable_assumeIsolated<T : Sendable>(
155160
_ operation: @MainActor () throws -> T,
156161
_ file: StaticString, _ line: UInt
157162
) rethrows -> T {

stdlib/public/Concurrency/Task+TaskExecutor.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,15 @@ public func withTaskExecutorPreference<T, Failure>(
164164
//
165165
// This function also doubles as an ABI-compatibility shim predating the
166166
// introduction of #isolation.
167+
@abi(
168+
func withTaskExecutorPreference<T: Sendable>(
169+
_ taskExecutor: (any TaskExecutor)?,
170+
operation: @Sendable () async throws -> T
171+
) async rethrows -> T
172+
)
167173
@_unavailableInEmbedded
168174
@available(SwiftStdlib 6.0, *)
169175
@_unsafeInheritExecutor // for ABI compatibility
170-
@_silgen_name("$ss26withTaskExecutorPreference_9operationxSch_pSg_xyYaYbKXEtYaKs8SendableRzlF")
171176
public func _unsafeInheritExecutor_withTaskExecutorPreference<T: Sendable>(
172177
_ taskExecutor: (any TaskExecutor)?,
173178
operation: @Sendable () async throws -> T

stdlib/public/Concurrency/TaskCancellation.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,14 @@ public func withTaskCancellationHandler<T>(
8989
//
9090
// This function also doubles as an ABI-compatibility shim predating the
9191
// introduction of #isolation.
92+
@abi(
93+
func withTaskCancellationHandler<T>(
94+
operation: () async throws -> T,
95+
onCancel handler: @Sendable () -> Void
96+
) async rethrows -> T
97+
)
9298
@_unsafeInheritExecutor // ABI compatibility with Swift 5.1
9399
@available(SwiftStdlib 5.1, *)
94-
@_silgen_name("$ss27withTaskCancellationHandler9operation8onCancelxxyYaKXE_yyYbXEtYaKlF")
95100
public func _unsafeInheritExecutor_withTaskCancellationHandler<T>(
96101
operation: () async throws -> T,
97102
onCancel handler: @Sendable () -> Void

stdlib/public/Concurrency/TaskGroup.swift

+17-3
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,15 @@ public func withTaskGroup<ChildTaskResult, GroupResult>(
9797
//
9898
// This function also doubles as an ABI-compatibility shim predating the
9999
// introduction of #isolation.
100+
@abi(
101+
@preconcurrency // TaskGroup.ChildTaskResult: Sendable
102+
func withTaskGroup<ChildTaskResult, GroupResult>(
103+
of childTaskResultType: ChildTaskResult.Type,
104+
returning returnType: GroupResult.Type,
105+
body: (inout TaskGroup<ChildTaskResult>) async -> GroupResult
106+
) async -> GroupResult
107+
)
100108
@available(SwiftStdlib 5.1, *)
101-
@_silgen_name("$ss13withTaskGroup2of9returning4bodyq_xm_q_mq_ScGyxGzYaXEtYar0_lF")
102109
@_unsafeInheritExecutor // for ABI compatibility
103110
@inlinable
104111
public func _unsafeInheritExecutor_withTaskGroup<ChildTaskResult, GroupResult>(
@@ -243,8 +250,15 @@ public func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
243250
//
244251
// This function also doubles as an ABI-compatibility shim predating the
245252
// introduction of #isolation.
253+
@abi(
254+
@preconcurrency // ThrowingTaskGroup.ChildTaskResult: Sendable
255+
func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
256+
of childTaskResultType: ChildTaskResult.Type,
257+
returning returnType: GroupResult.Type,
258+
body: (inout ThrowingTaskGroup<ChildTaskResult, Error>) async throws -> GroupResult
259+
) async rethrows -> GroupResult
260+
)
246261
@available(SwiftStdlib 5.1, *)
247-
@_silgen_name("$ss21withThrowingTaskGroup2of9returning4bodyq_xm_q_mq_Scgyxs5Error_pGzYaKXEtYaKr0_lF")
248262
@_unsafeInheritExecutor // for ABI compatibility
249263
public func _unsafeInheritExecutor_withThrowingTaskGroup<ChildTaskResult, GroupResult>(
250264
of childTaskResultType: ChildTaskResult.Type,
@@ -690,7 +704,7 @@ public struct ThrowingTaskGroup<ChildTaskResult: Sendable, Failure: Error> {
690704
return try await _taskGroupWaitNext(group: _group)
691705
}
692706

693-
@_silgen_name("$sScg10nextResults0B0Oyxq_GSgyYaKF")
707+
@abi(mutating func nextResult() async throws -> Result<ChildTaskResult, Failure>?)
694708
@usableFromInline
695709
mutating func nextResultForABI() async throws -> Result<ChildTaskResult, Failure>? {
696710
do {

stdlib/public/Concurrency/TaskLocal.swift

+14-2
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,16 @@ public final class TaskLocal<Value: Sendable>: Sendable, CustomStringConvertible
221221
//
222222
// This function also doubles as an ABI-compatibility shim predating the
223223
// introduction of #isolation.
224+
@abi(
225+
func withValue<R>(
226+
_ valueDuringOperation: Value,
227+
operation: () async throws -> R,
228+
file: String, line: UInt
229+
) async rethrows -> R
230+
)
224231
@discardableResult
225232
@_unsafeInheritExecutor // ABI compatibility with Swift 5.1
226233
@available(SwiftStdlib 5.1, *)
227-
@_silgen_name("$ss9TaskLocalC9withValue_9operation4file4lineqd__x_qd__yYaKXESSSutYaKlF")
228234
public func _unsafeInheritExecutor_withValue<R>(
229235
_ valueDuringOperation: Value,
230236
operation: () async throws -> R,
@@ -265,7 +271,13 @@ public final class TaskLocal<Value: Sendable>: Sendable, CustomStringConvertible
265271
return try await operation()
266272
}
267273

268-
@_silgen_name("$ss9TaskLocalC13withValueImpl_9operation4file4lineqd__xn_qd__yYaKXESSSutYaKlF")
274+
@abi(
275+
func withValueImpl<R>(
276+
_ valueDuringOperation: __owned Value,
277+
operation: () async throws -> R,
278+
file: String, line: UInt
279+
) async rethrows -> R
280+
)
269281
@inlinable
270282
@discardableResult
271283
@_unsafeInheritExecutor // internal for backwards compatibility; though may be able to be removed safely?

stdlib/public/Distributed/DistributedActor.swift

+20-7
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,15 @@ extension DistributedActor {
362362
/// state.
363363
///
364364
/// When the actor is remote, the closure won't be executed and this function will return nil.
365+
@abi(
366+
// We need to @abi here because the signature is the same as
367+
// `__separately_compiled_typed_throws_whenLocal(_:)`, and even though this
368+
// is @AEIC, the symbol name would conflict.
369+
nonisolated func __typed_throws_whenLocal<T: Sendable, E>(
370+
_ body: @Sendable (isolated Self) async throws(E) -> T
371+
) async throws(E) -> T?
372+
)
365373
@_alwaysEmitIntoClient
366-
// we need to silgen_name here because the signature is the same as __abi_whenLocal,
367-
// and even though this is @AEIC, the symbol name would conflict.
368-
@_silgen_name("$s11Distributed0A5ActorPAAE20whenLocalTypedThrowsyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lF")
369374
public nonisolated func whenLocal<T: Sendable, E>(
370375
_ body: @Sendable (isolated Self) async throws(E) -> T
371376
) async throws(E) -> T? {
@@ -380,18 +385,26 @@ extension DistributedActor {
380385
// ABI: This is a workaround when in Swift 6 this method was introduced
381386
// in order to support typed-throws, but missed to add @_aeic.
382387
// In practice, this method should not ever be used by anyone, ever.
388+
@abi(
389+
nonisolated func whenLocal<T: Sendable, E>(
390+
_ body: @Sendable (isolated Self) async throws(E) -> T
391+
) async throws(E) -> T?
392+
)
383393
@usableFromInline
384-
@_silgen_name("$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lF")
385-
internal nonisolated func __abi_whenLocal<T: Sendable, E>(
394+
nonisolated func __separately_compiled_typed_throws_whenLocal<T: Sendable, E>(
386395
_ body: @Sendable (isolated Self) async throws(E) -> T
387396
) async throws(E) -> T? {
388397
try await whenLocal(body)
389398
}
390399

391400
// ABI: Historical whenLocal, rethrows was changed to typed throws `throws(E)`
392-
@_silgen_name("$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbKXEYaKs8SendableRd__lF")
401+
@abi(
402+
nonisolated func whenLocal<T: Sendable>(
403+
_ body: @Sendable (isolated Self) async throws -> T
404+
) async rethrows -> T?
405+
)
393406
@usableFromInline
394-
nonisolated func __abi_whenLocal<T: Sendable>(
407+
nonisolated func __rethrows_whenLocal<T: Sendable>(
395408
_ body: @Sendable (isolated Self) async throws -> T
396409
) async rethrows -> T? {
397410
try await whenLocal(body)

stdlib/public/Distributed/DistributedAssertions.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,15 @@ extension DistributedActor {
179179
}
180180
}
181181

182+
@abi(
183+
nonisolated func assumeIsolated<T /* not ': Sendable' */>(
184+
_ operation: (isolated Self) throws -> T,
185+
file: StaticString, line: UInt
186+
) rethrows -> T
187+
)
182188
@available(SwiftStdlib 5.9, *)
183189
@usableFromInline
184-
@_silgen_name("$s11Distributed0A5ActorPAAE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKlF")
185-
internal nonisolated func __abi__assumeIsolated<T : Sendable>(
190+
internal nonisolated func __nonsendable_assumeIsolated<T : Sendable>(
186191
_ operation: (isolated Self) throws -> T,
187192
_ file: StaticString, _ line: UInt
188193
) rethrows -> T {

stdlib/public/core/Array.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -1613,12 +1613,16 @@ extension Array {
16131613

16141614
// Superseded by the typed-throws version of this function, but retained
16151615
// for ABI reasons.
1616+
@abi(
1617+
mutating func withUnsafeMutableBufferPointer<R>(
1618+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1619+
) rethrows -> R
1620+
)
16161621
@_semantics("array.withUnsafeMutableBufferPointer")
16171622
@_effects(notEscaping self.value**)
16181623
@usableFromInline
16191624
@inline(__always)
1620-
@_silgen_name("$sSa30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1621-
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1625+
mutating func __rethrows_withUnsafeMutableBufferPointer<R>(
16221626
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
16231627
) rethrows -> R {
16241628
_makeMutableAndUnique()

stdlib/public/core/ArrayBuffer.swift

+12-4
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,13 @@ extension _ArrayBuffer {
646646
/// created on-demand.
647647
// Superseded by the typed-throws version of this function, but retained
648648
// for ABI reasons.
649+
@abi(
650+
func withUnsafeBufferPointer<R>(
651+
_ body: (UnsafeBufferPointer<Element>) throws -> R
652+
) rethrows -> R
653+
)
649654
@usableFromInline
650-
@_silgen_name("$ss12_ArrayBufferV010withUnsafeB7Pointeryqd__qd__SRyxGKXEKlF")
651-
internal func __abi_withUnsafeBufferPointer<R>(
655+
internal func __rethrows_withUnsafeBufferPointer<R>(
652656
_ body: (UnsafeBufferPointer<Element>) throws -> R
653657
) rethrows -> R {
654658
if _fastPath(_isNative) {
@@ -676,9 +680,13 @@ extension _ArrayBuffer {
676680

677681
// Superseded by the typed-throws version of this function, but retained
678682
// for ABI reasons.
683+
@abi(
684+
mutating func withUnsafeMutableBufferPointer<R>(
685+
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
686+
) rethrows -> R
687+
)
679688
@usableFromInline
680-
@_silgen_name("$ss12_ArrayBufferV017withUnsafeMutableB7Pointeryqd__qd__SryxGKXEKlF")
681-
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
689+
internal mutating func __rethrows_withUnsafeMutableBufferPointer<R>(
682690
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
683691
) rethrows -> R {
684692
return try unsafe withUnsafeMutableBufferPointer(body)

0 commit comments

Comments
 (0)