|
| 1 | +# Underscored Attributes Reference |
| 2 | + |
| 3 | +**WARNING:** This information is provided primarily for compiler and standard |
| 4 | +library developers. Usage of these attributes outside of the Swift monorepo |
| 5 | +is STRONGLY DISCOURAGED. |
| 6 | + |
| 7 | +The Swift reference has a chapter discussing [stable attributes][Attributes]. |
| 8 | +This document is intended to serve as a counterpart describing underscored |
| 9 | +attributes, whose semantics are subject to change and most likely need to |
| 10 | +go through the Swift evolution process before being stabilized. |
| 11 | + |
| 12 | +[Attributes]: https://docs.swift.org/swift-book/ReferenceManual/Attributes.html |
| 13 | + |
| 14 | +The attributes are organized in alphabetical order. |
| 15 | + |
| 16 | +## `@_alignment(numericValue)` |
| 17 | + |
| 18 | +Allows controlling the alignment of a type. |
| 19 | + |
| 20 | +The alignment value specified must be a power of two, and cannot be less |
| 21 | +than the "natural" alignment of the type that would otherwise be used by |
| 22 | +the Swift ABI. This attribute is intended for the SIMD types in the standard |
| 23 | +library which use it to increase the alignment of their internal storage to at |
| 24 | +least 16 bytes. |
| 25 | + |
| 26 | +## `@_alwaysEmitIntoClient` |
| 27 | + |
| 28 | +Forces the body of a function to be emitted into client code. |
| 29 | + |
| 30 | +Note that this is distinct from `@inline(__always)`; it doesn't force inlining |
| 31 | +at call-sites, it only means that the implementation is compiled into the |
| 32 | +module which uses the code. |
| 33 | + |
| 34 | +This means that `@_alwaysEmitIntoClient` definitions are _not_ part of the |
| 35 | +defining module's ABI, so changing the implementation at a later stage |
| 36 | +does not break ABI. |
| 37 | + |
| 38 | +Most notably, default argument expressions are implicitly |
| 39 | +`@_alwaysEmitIntoClient`, which means that adding a default argument to a |
| 40 | +function which did not have one previously does not break ABI. |
| 41 | + |
| 42 | +## `@_borrowed` |
| 43 | + |
| 44 | +Indicates that the [conservative access pattern](/docs/Lexicon.md#access-pattern) |
| 45 | +for some storage (a subscript or a property) should use the `_read` accessor |
| 46 | +instead of `get`. |
| 47 | + |
| 48 | +For more details, see the forum post on |
| 49 | +[Value ownership when reading from a storage declaration](https://forums.swift.org/t/value-ownership-when-reading-from-a-storage-declaration/15076). |
| 50 | + |
| 51 | +## `@_cdecl("cName")` |
| 52 | + |
| 53 | +Similar to `@_silgen_name` but uses the C calling convention. |
| 54 | + |
| 55 | +This attribute doesn't have very well-defined semantics. Type bridging is not |
| 56 | +done, so the parameter and return types should correspond directly to types |
| 57 | +accessible in C. In most cases, it is preferable to define a static method |
| 58 | +on an `@objc` class instead of using `@_cdecl`. |
| 59 | + |
| 60 | +For potential ideas on stabilization, see |
| 61 | +[Formalizing `@cdecl`](https://forums.swift.org/t/formalizing-cdecl/40677). |
| 62 | + |
| 63 | +## `@_disfavoredOverload` |
| 64 | + |
| 65 | +Marks an overload that the type checker should try to avoid using. When the |
| 66 | +expression type checker is considering overloads, it will prefer a solution |
| 67 | +with fewer `@_disfavoredOverload` declarations over one with more of them. |
| 68 | + |
| 69 | +Use `@_disfavoredOverload` to work around known bugs in the overload |
| 70 | +resolution rules that cannot be immediately fixed without a source break. |
| 71 | +Don't use it to adjust overload resolution rules that are otherwise sensible |
| 72 | +but happen to produce undesirable results for your particular API; it will |
| 73 | +likely be removed or made into a no-op eventually, and then you will be |
| 74 | +stuck with an overload set that cannot be made to function in the way |
| 75 | +you intend. |
| 76 | + |
| 77 | +`@_disfavoredOverload` was first introduced to work around a bug in overload |
| 78 | +resolution with `ExpressibleByXYZLiteral` types. The type checker strongly |
| 79 | +prefers to give literals their default type (e.g. `Int` for |
| 80 | +`ExpressibleByIntegerLiteral`, `String` for `ExpressibleByStringLiteral`, |
| 81 | +etc.). If an API should prefer some other type, but accept the default too, |
| 82 | + marking the declaration taking the default type with `@_disfavoredOverload` |
| 83 | + gives the desired behavior: |
| 84 | + |
| 85 | +```swift |
| 86 | +extension LocalizedStringKey: ExpressibleByStringLiteral { ... } |
| 87 | + |
| 88 | +extension Text { |
| 89 | + // We want `Text("foo")` to use this initializer: |
| 90 | + init(_ key: LocalizedStringKey) { ... } |
| 91 | + |
| 92 | + // But without @_disfavoredOverload, it would use this one instead, |
| 93 | + // because that lets it give the literal its default type: |
| 94 | + @_disfavoredOverload init<S: StringProtocol>(_ str: S) { ... } |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +## `@_dynamicReplacement(for:)` |
| 99 | + |
| 100 | +Marks a function as the dynamic replacement for another `dynamic` function. |
| 101 | +This is similar to method swizzling in other languages such as Objective-C, |
| 102 | +except that the replacement happens at program start (or loading a shared |
| 103 | +library), instead of at an arbitrary point in time. |
| 104 | + |
| 105 | +For more details, see the forum post on |
| 106 | +[Dynamic method replacement](https://forums.swift.org/t/dynamic-method-replacement/16619). |
| 107 | + |
| 108 | +## `@_distributedActorIndependent` |
| 109 | + |
| 110 | +Marks a specific property of a distributed actor to be available even if the |
| 111 | +actor is remote. |
| 112 | + |
| 113 | +This only applies to two distributed actor properties `address` and `transport`. |
| 114 | +It cannot be safely declared on any properties defined by ordinary Swift code. |
| 115 | + |
| 116 | +## `@_effects(effectname)` |
| 117 | + |
| 118 | +Tells the compiler that the implementation of the defined function is limited |
| 119 | +to certain side effects. The attribute argument specifies the kind of side |
| 120 | +effect limitations that apply to the function including any other functions |
| 121 | +it calls. This is used to provide information to the optimizer that it can't |
| 122 | +already infer from static analysis. |
| 123 | + |
| 124 | +Changing the implementation in a way that violates the optimizer's assumptions |
| 125 | +about the effects results in undefined behavior. |
| 126 | + |
| 127 | +For more details, see [OptimizerEffects.rst](/docs/Proposals/OptimizerEffects.rst). |
| 128 | + |
| 129 | +## `@_exported` |
| 130 | + |
| 131 | +Re-exports all declarations from an imported module. |
| 132 | + |
| 133 | +This attribute is most commonly used by overlays. |
| 134 | + |
| 135 | +```swift |
| 136 | +// module M |
| 137 | +func f() {} |
| 138 | + |
| 139 | +// module N |
| 140 | +@_exported import M |
| 141 | + |
| 142 | +// module P |
| 143 | +import N |
| 144 | +func g() { |
| 145 | + N.f() // OK |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +## `@_fixed_layout` |
| 150 | + |
| 151 | +Same as `@frozen` but also works for classes. |
| 152 | + |
| 153 | +With `@_fixed_layout` classes, vtable layout still happens dynamically, so |
| 154 | +non-public virtual methods can be removed, new virtual methods can be added, |
| 155 | +and existing virtual methods can be reordered. |
| 156 | + |
| 157 | +## `@_hasInitialValue` |
| 158 | + |
| 159 | +Marks that a property has an initializing expression. |
| 160 | + |
| 161 | +This information is lost in the swiftinterface, |
| 162 | +but it is required as it results in a symbol for the initializer |
| 163 | +(if a class/struct `init` is inlined, it will call initializers |
| 164 | +for properties that it doesn't initialize itself). |
| 165 | +This information is necessary for correct TBD file generation. |
| 166 | + |
| 167 | +## `@_hasMissingDesignatedInitializers` |
| 168 | + |
| 169 | +Indicates that there may be designated initializers that are |
| 170 | +not printed in the swiftinterface file for a particular class. |
| 171 | + |
| 172 | +This attribute is needed for the initializer model to maintain correctness when |
| 173 | +[library evolution](/docs/LibraryEvolution.rst) is enabled. This is because a |
| 174 | +class may have non-public designated initializers, and Swift allows the |
| 175 | +inheritance of convenience initializers if and only if the subclass overrides |
| 176 | +(or has synthesized overrides) of every designated initializer in its |
| 177 | +superclass. Consider the following code: |
| 178 | + |
| 179 | +```swift |
| 180 | +// Lib.swift |
| 181 | +open class A { |
| 182 | + init(invisible: ()) {} |
| 183 | + |
| 184 | + public init(visible: ()) {} |
| 185 | + public convenience init(hi: ()) { self.init(invisible: ()) } |
| 186 | +} |
| 187 | + |
| 188 | +// Client.swift |
| 189 | +class B : A { |
| 190 | + var x: String |
| 191 | + |
| 192 | + public override init(visible: ()) { |
| 193 | + self.x = "Garbage" |
| 194 | + super.init(visible: ()) |
| 195 | + } |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +In this case, if `B` were allowed to inherit the convenience initializer |
| 200 | +`A.init(invisible:)` then an instance created via `B(hi: ())` would fail |
| 201 | +to initialize `B.x` resulting in a memory safety hole. What's worse is |
| 202 | +there is no way to close this safety hole because the user cannot override |
| 203 | +the invisible designated initializer because they lack sufficient visibility. |
| 204 | + |
| 205 | +## `@_hasStorage` |
| 206 | + |
| 207 | +Marks a property as being a stored property in a swiftinterface. |
| 208 | + |
| 209 | +For `@frozen` types, the compiler needs to be able to tell whether a particular |
| 210 | +property is stored or computed to correctly perform type layout. |
| 211 | + |
| 212 | +``` |
| 213 | +@frozen struct S { |
| 214 | + @_hasStorage var x: Int { get set } // stored |
| 215 | + var y: Int { get set } // computed |
| 216 | +} |
| 217 | +``` |
| 218 | + |
| 219 | +## `@_implementationOnly` |
| 220 | + |
| 221 | +Used to mark an imported module as an implementation detail. |
| 222 | +This prevents types from that module being exposed in API |
| 223 | +(types of public functions, constraints in public extension etc.) |
| 224 | +and ABI (usage in `@inlinable` code). |
| 225 | + |
| 226 | +## `@_implements(ProtocolName, Requirement)` |
| 227 | + |
| 228 | +An attribute that indicates that a function with one name satisfies |
| 229 | +a protocol requirement with a different name. This is especially useful |
| 230 | +when two protocols declare a requirement with the same name, but the |
| 231 | +conforming type wishes to offer two separate implementations. |
| 232 | + |
| 233 | +```swift |
| 234 | +protocol P { func foo() } |
| 235 | + |
| 236 | +protocol Q { func foo() } |
| 237 | + |
| 238 | +struct S : P, Q { |
| 239 | + @_implements(P, foo()) |
| 240 | + func foo_p() {} |
| 241 | + @_implements(Q, foo()) |
| 242 | + func foo_q() {} |
| 243 | +} |
| 244 | +``` |
| 245 | + |
| 246 | +## `@_implicitSelfCapture` |
| 247 | + |
| 248 | +Allows access to `self` inside a closure without explicitly capturing it, |
| 249 | +even when `Self` is a reference type. |
| 250 | + |
| 251 | +```swift |
| 252 | +class C { |
| 253 | + func f() {} |
| 254 | + func g(_: @escaping () -> Void { |
| 255 | + g({ f() }) // error: call to method 'f' in closure requires explicit use of 'self' |
| 256 | + } |
| 257 | + func h(@_implicitSelfCapture _: @escaping () -> Void) { |
| 258 | + h({ f() }) // ok |
| 259 | + } |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +## `@_inheritActorContext` |
| 264 | + |
| 265 | +(Note that it is "inherit", not "inherits", unlike below.) |
| 266 | + |
| 267 | +Marks that a `@Sendable async` closure argument should inherited the actor |
| 268 | +context (i.e. what actor it should be run on) based on the declaration site |
| 269 | +of the closure. This is different from the typical behavior, where the closure |
| 270 | +may be runnable anywhere unless its type specifically declares that it will |
| 271 | +run on a specific actor. |
| 272 | + |
| 273 | +This new attribute can be used on parameters of `@Sendable async` type |
| 274 | +to indicate that the closures arguments passed to such parameters |
| 275 | +should inherit the actor context where they are formed, which is not |
| 276 | +the normal behavior for `@Sendable` closures. |
| 277 | + |
| 278 | +## `@_inheritsConvenienceInitializers` |
| 279 | + |
| 280 | +An attribute that signals that a class declaration inherits its convenience |
| 281 | +initializers from its superclass. This implies that all designated initializers |
| 282 | +-- even those that may not be visible in a swiftinterface file -- are |
| 283 | +overridden. This attribute is often printed alongside |
| 284 | +`@_hasMissingDesignatedInitializers` in this case. |
| 285 | + |
| 286 | +## `@_marker` |
| 287 | + |
| 288 | +Indicates that a protocol is a marker protocol. Marker protocols represent some |
| 289 | +meaningful property at compile-time but have no runtime representation. |
| 290 | + |
| 291 | +For more details, see [SE-0302](https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#marker-protocols), which introduces marker protocols. |
| 292 | + |
| 293 | +At the moment, the language only has one marker protocol: `Sendable`. |
| 294 | + |
| 295 | +Fun fact: Rust has a very similar concept called |
| 296 | +[marker traits](https://doc.rust-lang.org/std/marker/index.html), |
| 297 | +including one called `Send`, |
| 298 | +which inspired the design of `Sendable`. |
| 299 | + |
| 300 | +## `@_nonEphemeral` |
| 301 | + |
| 302 | +Marks a function parameter that cannot accept a temporary pointer produced from |
| 303 | +an inout-to-pointer, array-to-pointer, or string-to-pointer conversion. Such a |
| 304 | +parameter may only accept a pointer that is guaranteed to outlive the duration |
| 305 | +of the function call. |
| 306 | + |
| 307 | +Attempting to pass a temporary pointer to an `@_nonEphemeral` parameter will |
| 308 | +produce a warning. This attribute is primarily used within the standard library |
| 309 | +on the various `UnsafePointer` initializers to warn users about |
| 310 | +the undefined behavior caused by using a temporary pointer conversion as an |
| 311 | +argument: |
| 312 | + |
| 313 | +```swift |
| 314 | +func baz() { |
| 315 | + var x = 0 |
| 316 | + |
| 317 | + // warning: Initialization of 'UnsafePointer<Int>' results in a dangling pointer |
| 318 | + let ptr = UnsafePointer(&x) |
| 319 | + |
| 320 | + // warning: Initialization of 'UnsafePointer<Int>' results in a dangling pointer |
| 321 | + let ptr2 = UnsafePointer([1, 2, 3]) |
| 322 | +} |
| 323 | +``` |
| 324 | + |
| 325 | +The temporary pointer conversion produces a pointer that is only |
| 326 | +guaranteed to be valid for the duration of the call to the initializer, |
| 327 | +and becomes invalid once the call ends. |
| 328 | +So the newly created `UnsafePointer` will be dangling. |
| 329 | + |
| 330 | +One exception to this is that inout-to-pointer conversions |
| 331 | +on static stored properties and global stored properties |
| 332 | +produce non-ephemeral pointers, as long as they have no observers: |
| 333 | + |
| 334 | +```swift |
| 335 | +var global = 0 |
| 336 | + |
| 337 | +struct S { |
| 338 | + static var staticVar = 0 |
| 339 | +} |
| 340 | + |
| 341 | +func baz() { |
| 342 | + let ptr = UnsafePointer(&global) // okay |
| 343 | + let ptr2 = UnsafePointer(&S.staticVar) // okay |
| 344 | +} |
| 345 | +``` |
| 346 | + |
| 347 | +Additionally, if they are of a tuple or struct type, their stored members |
| 348 | +without observers may also be passed inout as non-ephemeral pointers. |
| 349 | + |
| 350 | +For more details, see the educational note on |
| 351 | +[temporary pointer usage](/userdocs/diagnostics/temporary-pointers.md). |
| 352 | + |
| 353 | +## `@_nonoverride` |
| 354 | + |
| 355 | +Marks a declaration that is not an override of another. |
| 356 | +When the `-warn-implicit-overrides` flag is used, a warning is issued when a |
| 357 | +protocol restates a requirement from another protocol it refines without |
| 358 | +annotating the declaration with either `override` or `@_nonoverride`. |
| 359 | + |
| 360 | +An `override` annotation causes the overriding declaration to be treated |
| 361 | +identically to the overridden declaration; a conforming type can only |
| 362 | +provide one implementation ("witness"). Restating a protocol requirement |
| 363 | +and then marking it as an `override` is generally only needed to help |
| 364 | +associated type inference, and many `override` annotations correlate |
| 365 | +closely with ABI FIXMEs. |
| 366 | + |
| 367 | +Meanwhile, `@_nonoverride` is the "opposite" of `override`, allowing two |
| 368 | +protocol requirements to be treated independently; a conforming type can |
| 369 | +provide a distinct witness for each requirement (for example, by using |
| 370 | +`@_implements`). Use `@_nonoverride` when semantics differ between the |
| 371 | +two requirements. For example, `BidirectionalCollection.index(_:offsetBy:)` |
| 372 | +allows negative offsets, while `Collection.index(_:offsetBy:)` does not, |
| 373 | +and therefore the former is marked `@_nonoverride`. |
| 374 | + |
| 375 | +The `@_nonoverride` annotation can also be specified on class members in |
| 376 | +addition to protocol members. Since it is the "opposite" of `override`, it can |
| 377 | +be used to suppress "near-miss" diagnostics for declarations that are similar |
| 378 | +to but not meant to override another declaration, and it can be used to |
| 379 | +intentionally break the override chain, creating an overload instead of an |
| 380 | +override. |
| 381 | + |
| 382 | +This attribute and the corresponding `-warn-implicit-overrides` flag are |
| 383 | +used when compiling the standard library and overlays. |
| 384 | + |
| 385 | +## `@_objc_non_lazy_realization` |
| 386 | + |
| 387 | +Marks a class as being non-lazily (i.e. eagerly) [realized](/docs/Lexicon.md#realization). |
| 388 | + |
| 389 | +This is used for declarations which may be statically referenced and wouldn't |
| 390 | +go through the normal lazy realization paths. For example, the empty array |
| 391 | +class must be non-lazily realized, because empty arrays are statically |
| 392 | +allocated. Otherwise, passing the empty array object to other code without |
| 393 | +triggering realization could allow for the unrealized empty array class to be |
| 394 | +passed to ObjC runtime APIs which only operate on realized classes, resulting |
| 395 | +in a crash. |
| 396 | + |
| 397 | +## `@_optimize([none|size|speed])` |
| 398 | + |
| 399 | +Controls the compiler's optimization mode. This attribute is analogous to the |
| 400 | +command-line flags `-Onone`, `-Osize` and `-Ospeed` respectively, but limited |
| 401 | +to a single function body. |
| 402 | + |
| 403 | +`@_optimize(none)` is handy for diagnosing and reducing compiler bugs as well |
| 404 | +as improving debugging in Release builds. |
| 405 | + |
| 406 | +## `@_originallyDefinedIn(module: "ModuleName", availabilitySpec...)` |
| 407 | + |
| 408 | +Marks a declaration as being originally defined in a different module, |
| 409 | +changing the name mangling. This can be used to move declarations |
| 410 | +from a module to one of the modules it imports without breaking clients. |
| 411 | + |
| 412 | +Consider the following example where a framework ToasterKit needs |
| 413 | +to move some APIs to a lower-level framework ToasterKitCore. |
| 414 | +Here are the necessary changes: |
| 415 | + |
| 416 | +1. Add a linker flag `-reexport_framework ToasterKitCore` for ToasterKit. |
| 417 | + This ensures all symbols defined in ToasterKitCore will be accessible during |
| 418 | + runtime via ToasterKit, so existing apps continue to run. |
| 419 | +2. In ToasterKit, use `@_exported import ToasterKitCore`. |
| 420 | + This ensures existing source code that only imports ToasterKit continues to |
| 421 | + type-check. |
| 422 | +3. Move the necessary declarations from ToasterKit to ToasterKitCore. |
| 423 | + The moved declaration should have two attributes: |
| 424 | + - `@available` indicating when the declaration was introduced in ToasterKit. |
| 425 | + - `@_originallyDefinedIn` indicating the original module and when the |
| 426 | + declaration was moved to ToasterKitCore. |
| 427 | + ```swift |
| 428 | + @available(toasterOS 42, *) |
| 429 | + @_originallyDefinedIn(module: "ToasterKit", toasterOS 57) |
| 430 | + enum Toast { |
| 431 | + case underdone |
| 432 | + case perfect |
| 433 | + case burnt |
| 434 | + } |
| 435 | + ``` |
| 436 | +4. Add Swift compiler flags `-Xfrontend -emit-ldadd-cfile-path -Xfrontend /tmp/t.c` |
| 437 | + to ToasterKitCore's build settings. Add the emitted `/tmp/t.c` file to |
| 438 | + ToasterKit's compilation. |
| 439 | + This ensures when an app is built for deployment targets prior to the symbols' move, |
| 440 | + the app will look for these symbols in ToasterKit instead of ToasterKitCore. |
| 441 | + |
| 442 | +More generally, mutliple availabilities can be specified, like so: |
| 443 | + |
| 444 | +```swift |
| 445 | +@available(toasterOS 42, bowlOS 54, mugOS 54, *) |
| 446 | +@_originallyDefinedIn(module: "ToasterKit", toasterOS 57, bowlOS 69, mugOS 69) |
| 447 | +enum Toast { ... } |
| 448 | +``` |
| 449 | + |
| 450 | +## `@_private(sourceFile: "FileName.swift")` |
| 451 | + |
| 452 | +Fully bypasses access control, allowing access to private declarations |
| 453 | +in the imported module. The imported module needs to be compiled with |
| 454 | +`-Xfrontend -enable-private-imports` for this to work. |
| 455 | + |
| 456 | +## `@_semantics("uniquely.recognized.id")` |
| 457 | + |
| 458 | +Allows the optimizer to make use of some key invariants in performance critical |
| 459 | +data types, especially `Array`. Since the implementation of these data types |
| 460 | +is written in Swift using unsafe APIs, without these attributes the optimizer |
| 461 | +would need to make conservative assumptions. |
| 462 | + |
| 463 | +Changing the implementation in a way that violates the optimizer's assumptions |
| 464 | +about the semantics results in undefined behavior. |
| 465 | + |
| 466 | +## `@_show_in_interface` |
| 467 | + |
| 468 | +Shows underscored protocols from the standard library in the generated interface. |
| 469 | + |
| 470 | +By default, SourceKit hides underscored protocols from the generated |
| 471 | +swiftinterface (for all modules, not just the standard library), but this |
| 472 | +attribute can be used to override that behavior for the standard library. |
| 473 | + |
| 474 | +## `@_silgen_name("cName")` |
| 475 | + |
| 476 | +Changes the symbol name for a function, similar to an ASM label in C, |
| 477 | +except that the platform symbol mangling (leading underscore on Darwin) |
| 478 | +is maintained. |
| 479 | + |
| 480 | +Since this has label-like behavior, it may not correspond to any declaration; |
| 481 | +if so, it is assumed that the function is implemented in C. |
| 482 | + |
| 483 | +A function defined by `@_silgen_name` is assumed to use the Swift ABI. |
| 484 | + |
| 485 | +For more details, see the |
| 486 | +[Standard Library Programmer's Manual](https://github.com/apple/swift/blob/main/docs/StandardLibraryProgrammersManual.md#_silgen_name). |
| 487 | + |
| 488 | +## `@_specialize(...)` |
| 489 | + |
| 490 | +Forces generation of a specialized implementation for a generic declaration. |
| 491 | + |
| 492 | +See [Generics.rst](/docs/Generics.rst) for more details. |
| 493 | + |
| 494 | +## `@_specializeExtension` |
| 495 | + |
| 496 | +Allows extending `@usableFromInline` internal types from foreign modules. |
| 497 | +Consider the following example involving two modules: |
| 498 | + |
| 499 | +```swift |
| 500 | +// Module A |
| 501 | +@usableFromInline |
| 502 | +internal struct S<T> { /* ... */ } |
| 503 | + |
| 504 | +// Module B |
| 505 | +import A |
| 506 | + |
| 507 | +@_specializeExtension |
| 508 | +extension S { // OK |
| 509 | + // add methods here |
| 510 | +} |
| 511 | + |
| 512 | +extension S /* or A.S */ { // error: cannot find 'S' in scope |
| 513 | +} |
| 514 | +``` |
| 515 | + |
| 516 | +This ability can be used to add specializations of existing methods |
| 517 | +in downstream libraries when used in conjunction with `@_specialize`. |
| 518 | + |
| 519 | +```swift |
| 520 | +// Module A |
| 521 | +@usableFromInline |
| 522 | +internal struct S<T> { |
| 523 | + @inlinable |
| 524 | + internal func doIt() { /* body */ } |
| 525 | +} |
| 526 | + |
| 527 | +// Module B |
| 528 | +import A |
| 529 | + |
| 530 | +@_specializeExtension |
| 531 | +extension S { // ok |
| 532 | + @_specialize(exported: true, target: doIt(), where T == Int) |
| 533 | + public func specializedDoIt() {} |
| 534 | +} |
| 535 | + |
| 536 | +// Module C |
| 537 | +import A |
| 538 | +import B |
| 539 | + |
| 540 | +func f(_ s: S<Int>) { |
| 541 | + s.doIt() // will call specialized version of doIt() where T == Int from B |
| 542 | +} |
| 543 | +``` |
| 544 | + |
| 545 | +## `@_spi(spiName)` |
| 546 | + |
| 547 | +Marks a declaration as SPI (System Programming Interface), instead of API. |
| 548 | +Modules exposing SPI and using library evolution generate an additional |
| 549 | +`.private.swiftinterface` file (with `-emit-private-module-interface-path`) |
| 550 | +in addition to the usual `.swiftinterface` file. This private interface exposes |
| 551 | +both API and SPI. |
| 552 | + |
| 553 | +Clients can access SPI by marking the import as `@_spi(spiName) import Module`. |
| 554 | +This design makes it easy to find out which clients are using certain SPIs by |
| 555 | +doing a textual search. |
| 556 | + |
| 557 | +## `@_staticInitializeObjCMetadata` |
| 558 | + |
| 559 | +Indicates that a static initializer should be emitted to register the |
| 560 | +Objective-C metadata when the image is loaded, rather than on first use of the |
| 561 | +Objective-C metadata. |
| 562 | + |
| 563 | +This attribute is inferred for `NSCoding` classes that won't |
| 564 | +have static Objective-C metadata or have an `@NSKeyedArchiveLegacy` attribute. |
| 565 | + |
| 566 | +## `@_transparent` |
| 567 | + |
| 568 | +Marks a function to be "macro-like", i.e., it is guaranteed to be inlined |
| 569 | +in debug builds. |
| 570 | + |
| 571 | +See [TransparentAttr.md](/docs/TransparentAttr.md) for more details. |
| 572 | + |
| 573 | +## `@_typeEraser(Proto)` |
| 574 | + |
| 575 | +Marks a concrete nominal type as one that implements type erasure for a |
| 576 | +protocol `Proto`. |
| 577 | + |
| 578 | +A type eraser has the following restrictions: |
| 579 | + |
| 580 | +1. It must be a concrete nominal type. |
| 581 | +2. It must not have more restrictive access than `Proto`. |
| 582 | +3. It must conform to `Proto`. |
| 583 | +4. It must have an initializer of the form `init<T: Proto>(erasing: T)`. |
| 584 | + - Other generic requirements are permitted as long as the `init` can always |
| 585 | + be called with a value of any type conforming to `Proto`. |
| 586 | + - The `init` cannot have more restrictive access than `Proto`. |
| 587 | + |
| 588 | +This feature was designed to be used for compiler-driven type erasure for |
| 589 | +dynamic replacement of functions with an opaque return type. |
| 590 | + |
| 591 | +## `@_weakLinked` |
| 592 | + |
| 593 | +Allows a declaration to be weakly-referenced, i.e., any references emitted by |
| 594 | +client modules to the declaration's symbol will have weak linkage. This means |
| 595 | +that client code will compile without the guarantee that the symbol will be |
| 596 | +available at runtime. This requires a dynamic safety check (such as using |
| 597 | +`dlsym (3)`); otherwise, accessing the symbol when it is unavailable leads |
| 598 | +to a runtime crash. |
| 599 | + |
| 600 | +This is an unsafe alternative to using `@available`, which is statically checked. |
| 601 | +If the availability of a library symbol is newer than the deployment target of |
| 602 | +the client, the symbol will be weakly linked, but checking for `@available` and |
| 603 | +`#(un)available` ensures that a symbol is not accessed when it is unavailable. |
| 604 | + |
| 605 | +## `@_unsafeMainActor`, `@_unsafeSendable` |
| 606 | + |
| 607 | +Marks a parameter's (function) type as `@MainActor` (`@Sendable`) in Swift 6 and |
| 608 | +within Swift 5 code that has adopted concurrency, but non-`@MainActor` |
| 609 | +(non-`@Sendable`) everywhere else. |
| 610 | + |
| 611 | +See the forum post on [Concurrency in Swift 5 and 6](https://forums.swift.org/t/concurrency-in-swift-5-and-6/49337) |
| 612 | +for more details. |
0 commit comments