Skip to content

Commit f3a443a

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

36 files changed

+408
-149
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 8 additions & 6 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ function(_compile_swift_files
633633
list(APPEND swift_flags "-enable-experimental-feature" "NonescapableTypes")
634634

635635
list(APPEND swift_flags "-enable-experimental-feature" "ExtensionImportVisiblity")
636+
list(APPEND swift_flags "-enable-experimental-feature" "ABIAttribute")
636637

637638
if (SWIFT_STDLIB_ENABLE_STRICT_CONCURRENCY_COMPLETE)
638639
list(APPEND swift_flags "-strict-concurrency=complete")

stdlib/public/Concurrency/AsyncStream.swift

Lines changed: 6 additions & 1 deletion
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+
public init(
335+
unfolding produce: @escaping /* not @Sendable*/ () async -> Element?,
336+
onCancel: (@Sendable () -> Void)? = nil
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

Lines changed: 12 additions & 2 deletions
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+
public 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+
public 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

Lines changed: 12 additions & 2 deletions
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+
public func withDiscardingTaskGroup<GroupResult>(
102+
returning returnType: GroupResult.Type = GroupResult.self,
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
@@ -513,9 +518,14 @@ public func withThrowingDiscardingTaskGroup<GroupResult>(
513518
return result
514519
}
515520

521+
@abi(
522+
public func withThrowingDiscardingTaskGroup<GroupResult>(
523+
returning returnType: GroupResult.Type = GroupResult.self,
524+
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult
525+
) async throws -> GroupResult
526+
)
516527
@available(SwiftStdlib 5.9, *)
517528
@_unsafeInheritExecutor // for ABI compatibility
518-
@_silgen_name("$ss31withThrowingDiscardingTaskGroup9returning4bodyxxm_xs0bcdE0Vys5Error_pGzYaKXEtYaKlF")
519529
public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
520530
returning returnType: GroupResult.Type = GroupResult.self,
521531
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult

stdlib/public/Concurrency/ExecutorAssertions.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,17 @@ extension Actor {
368368
}
369369
}
370370

371+
@abi(
372+
@usableFromInline
373+
@_unavailableInEmbedded
374+
internal nonisolated func assumeIsolated<T>(
375+
_ operation: (isolated Self) throws -> T,
376+
file: StaticString, line: UInt
377+
) rethrows -> T
378+
)
371379
@available(SwiftStdlib 5.9, *)
372380
@usableFromInline
373381
@_unavailableInEmbedded
374-
@_silgen_name("$sScAsE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKlF")
375382
internal nonisolated func __abi__assumeIsolated<T : Sendable>(
376383
_ operation: (isolated Self) throws -> T,
377384
_ file: StaticString, _ line: UInt

stdlib/public/Concurrency/MainActor.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,15 @@ extension MainActor {
148148
}
149149
}
150150

151+
@abi(
152+
@usableFromInline
153+
internal static func assumeIsolated<T>(
154+
_ operation: @MainActor () throws -> T,
155+
file: StaticString, line: UInt
156+
) rethrows -> T
157+
)
151158
@available(SwiftStdlib 5.9, *)
152159
@usableFromInline
153-
@_silgen_name("$sScM14assumeIsolated_4file4linexxyKScMYcXE_s12StaticStringVSutKlFZ")
154160
internal static func __abi__assumeIsolated<T : Sendable>(
155161
_ operation: @MainActor () throws -> T,
156162
_ file: StaticString, _ line: UInt

stdlib/public/Concurrency/Task+TaskExecutor.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,16 @@ 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+
@_unavailableInEmbedded
169+
public func withTaskExecutorPreference<T: Sendable>(
170+
_ taskExecutor: (any TaskExecutor)?,
171+
operation: @Sendable () async throws -> T
172+
) async rethrows -> T
173+
)
167174
@_unavailableInEmbedded
168175
@available(SwiftStdlib 6.0, *)
169176
@_unsafeInheritExecutor // for ABI compatibility
170-
@_silgen_name("$ss26withTaskExecutorPreference_9operationxSch_pSg_xyYaYbKXEtYaKs8SendableRzlF")
171177
public func _unsafeInheritExecutor_withTaskExecutorPreference<T: Sendable>(
172178
_ taskExecutor: (any TaskExecutor)?,
173179
operation: @Sendable () async throws -> T

stdlib/public/Concurrency/TaskCancellation.swift

Lines changed: 6 additions & 1 deletion
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+
public 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

Lines changed: 17 additions & 3 deletions
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+
public func withTaskGroup<ChildTaskResult, GroupResult>(
103+
of childTaskResultType: ChildTaskResult.Type,
104+
returning returnType: GroupResult.Type = GroupResult.self,
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+
public func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
256+
of childTaskResultType: ChildTaskResult.Type,
257+
returning returnType: GroupResult.Type = GroupResult.self,
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,
@@ -994,7 +1008,7 @@ public struct ThrowingTaskGroup<ChildTaskResult: Sendable, Failure: Error> {
9941008
return try await _taskGroupWaitNext(group: _group)
9951009
}
9961010

997-
@_silgen_name("$sScg10nextResults0B0Oyxq_GSgyYaKF")
1011+
@abi(public mutating func nextResult() async throws -> Result<ChildTaskResult, Failure>?)
9981012
@usableFromInline
9991013
mutating func nextResultForABI() async throws -> Result<ChildTaskResult, Failure>? {
10001014
do {

stdlib/public/Concurrency/TaskLocal.swift

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

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

stdlib/public/Distributed/DistributedActor.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,13 @@ extension DistributedActor {
363363
///
364364
/// When the actor is remote, the closure won't be executed and this function will return nil.
365365
@_alwaysEmitIntoClient
366-
// we need to silgen_name here because the signature is the same as __abi_whenLocal,
366+
// we need to @abi here because the signature is the same as __abi_whenLocal,
367367
// 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")
368+
@abi(
369+
public nonisolated func __api_whenLocal<T: Sendable, E>(
370+
_ body: @Sendable (isolated Self) async throws(E) -> T
371+
) async throws(E) -> T?
372+
)
369373
public nonisolated func whenLocal<T: Sendable, E>(
370374
_ body: @Sendable (isolated Self) async throws(E) -> T
371375
) async throws(E) -> T? {
@@ -380,16 +384,24 @@ extension DistributedActor {
380384
// ABI: This is a workaround when in Swift 6 this method was introduced
381385
// in order to support typed-throws, but missed to add @_aeic.
382386
// In practice, this method should not ever be used by anyone, ever.
387+
@abi(
388+
public nonisolated func whenLocal<T: Sendable, E>(
389+
_ body: @Sendable (isolated Self) async throws(E) -> T
390+
) async throws(E) -> T?
391+
)
383392
@usableFromInline
384-
@_silgen_name("$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lF")
385393
internal nonisolated func __abi_whenLocal<T: Sendable, E>(
386394
_ body: @Sendable (isolated Self) async throws(E) -> T
387395
) async throws(E) -> T? {
388396
try await whenLocal(body)
389397
}
390398

391399
// ABI: Historical whenLocal, rethrows was changed to typed throws `throws(E)`
392-
@_silgen_name("$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbKXEYaKs8SendableRd__lF")
400+
@abi(
401+
public nonisolated func whenLocal<T: Sendable>(
402+
_ body: @Sendable (isolated Self) async throws -> T
403+
) async rethrows -> T?
404+
)
393405
@usableFromInline
394406
nonisolated func __abi_whenLocal<T: Sendable>(
395407
_ body: @Sendable (isolated Self) async throws -> T

stdlib/public/Distributed/DistributedAssertions.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,12 @@ extension DistributedActor {
181181

182182
@available(SwiftStdlib 5.9, *)
183183
@usableFromInline
184-
@_silgen_name("$s11Distributed0A5ActorPAAE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKlF")
184+
@abi(
185+
public nonisolated func assumeIsolated<T /* not ': Sendable' */>(
186+
_ operation: (isolated Self) throws -> T,
187+
file: StaticString, line: UInt
188+
) rethrows -> T
189+
)
185190
internal nonisolated func __abi__assumeIsolated<T : Sendable>(
186191
_ operation: (isolated Self) throws -> T,
187192
_ file: StaticString, _ line: UInt

stdlib/public/core/Array.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,11 +1613,15 @@ extension Array {
16131613

16141614
// Superseded by the typed-throws version of this function, but retained
16151615
// for ABI reasons.
1616+
@abi(
1617+
public 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")
16211625
mutating func __abi_withUnsafeMutableBufferPointer<R>(
16221626
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
16231627
) rethrows -> R {

stdlib/public/core/ArrayBuffer.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,12 @@ extension _ArrayBuffer {
569569

570570
// Superseded by the typed-throws version of this function, but retained
571571
// for ABI reasons.
572+
@abi(
573+
public func withUnsafeBufferPointer<R>(
574+
_ body: (UnsafeBufferPointer<Element>) throws -> R
575+
) rethrows -> R
576+
)
572577
@usableFromInline
573-
@_silgen_name("$ss12_ArrayBufferV010withUnsafeB7Pointeryqd__qd__SRyxGKXEKlF")
574578
internal func __abi_withUnsafeBufferPointer<R>(
575579
_ body: (UnsafeBufferPointer<Element>) throws -> R
576580
) rethrows -> R {
@@ -599,8 +603,12 @@ extension _ArrayBuffer {
599603

600604
// Superseded by the typed-throws version of this function, but retained
601605
// for ABI reasons.
606+
@abi(
607+
public mutating func withUnsafeMutableBufferPointer<R>(
608+
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
609+
) rethrows -> R
610+
)
602611
@usableFromInline
603-
@_silgen_name("$ss12_ArrayBufferV017withUnsafeMutableB7Pointeryqd__qd__SryxGKXEKlF")
604612
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
605613
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
606614
) rethrows -> R {

stdlib/public/core/ArraySlice.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1212,10 +1212,14 @@ extension ArraySlice {
12121212

12131213
// Superseded by the typed-throws version of this function, but retained
12141214
// for ABI reasons.
1215+
@abi(
1216+
public mutating func withUnsafeMutableBufferPointer<R>(
1217+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1218+
) rethrows -> R
1219+
)
12151220
@_semantics("array.withUnsafeMutableBufferPointer")
12161221
@usableFromInline
12171222
@inline(__always)
1218-
@_silgen_name("$ss10ArraySliceV30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
12191223
mutating func __abi_withUnsafeMutableBufferPointer<R>(
12201224
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
12211225
) rethrows -> R {

0 commit comments

Comments
 (0)