diff --git a/TSPL.docc/LanguageGuide/Concurrency.md b/TSPL.docc/LanguageGuide/Concurrency.md index c62251c5d..c6012f708 100644 --- a/TSPL.docc/LanguageGuide/Concurrency.md +++ b/TSPL.docc/LanguageGuide/Concurrency.md @@ -1324,52 +1324,25 @@ struct TemperatureReading { --> To explicitly mark a type as not being sendable, -overriding an implicit conformance to the `Sendable` protocol, -use an extension: +write `~Sendable` after the type: ```swift -struct FileDescriptor { - let rawValue: CInt +struct FileDescriptor: ~Sendable { + let rawValue: Int } - -@available(*, unavailable) -extension FileDescriptor: Sendable { } ``` -The code above shows part of a wrapper around POSIX file descriptors. -Even though interface for file descriptors uses integers -to identify and interact with open files, -and integer values are sendable, -a file descriptor isn't safe to send across concurrency domains. - - -In the code above, -the `FileDescriptor` is a structure -that meets the criteria to be implicitly sendable. -However, the extension makes its conformance to `Sendable` unavailable, -preventing the type from being sendable. +For more information about +suppressing an implicit conformance to a protocol, +see . +These generic constraints that you don't have to write +are known as *implicit constraints*. +For example, both of the following function declarations +require `MyType` to be copyable: + +[`Copyable`]: https://developer.apple.com/documentation/swift/copyable + +```swift +function someFunction { ... } +function someFunction { ... } +``` + +Both declarations of `someFunction()` in the code above +require the generic type parameter `MyType` to be copyable. +In the first version, the constraint is implicit; +the second version lists the explicitly. +In most code, +types also implicitly conform to these common protocols. +For more information, +see . + +Because most types in Swift conform to these protocols, +writing them almost everywhere would be repetitive. +Instead, by marking only the exceptions, +your call out the places that omit a common constraint. +To suppress an implicit constraint, +write the protocol name with a tilde (`~`) in front of it. +You can read `~Copyable` as "maybe copyable" --- +this suppressed constraint allows +both copyable and noncopyable types in this position. +Note that `~Copyable` doesn't *require* the type to be noncopyable. +For example: + +```swift +func f(x: inout MyType) { + let x1 = x // The value of x1 is a copy of x's value. + let x2 = x // The value of x2 is a copy of x's value. +} + +func g(y: inout AnotherType) { + let y1 = y // The assignment consumes y's value. + let y2 = y // Error: Value consumed more than once. +} +``` + +In the code above, +the function `f()` implicitly requires `MyType` to be copyable. +Within the function body, +the value of `x` is copied to `x1` and `x2` in the assignment. +In contrast, `g()` suppresses the implicit constraint on `AnotherType`, +which allows you to pass either a copyable or noncopyable value. +Within the function body, +you can't copy the value of `y` +because `AnotherType` might be noncopyable. +Assignment consumes the value of `y` +and it's an error to consume that value more than once. +Noncopyable values like `y` +must be passed as in-out, borrowing, or consuming parameters --- +for more information, +see . + +For details about when generic code +includes an implicit constraint to a given protocol, +see the reference for that protocol. + +## Protocols that Have Only Semantic Requirements + +All of the example protocols above require some methods or properties, +but a protocol declaration doesn't have to include any requirements. +You can also use a protocol to describe *semantic* requirements --- +that is, requirements about how values of those types behave +and about operations that they support. + +The Swift standard library defines several protocols +that don't have any required methods or properties: + +- [`Sendable`][] for values that can be shared across concurrency domains, + as discussed in . +- [`Copyable`][] for values that Swift can copy + when you pass them to a function, + as discussed in . +- [`BitwiseCopyable`][] for values that can be copied, bit-by-bit. + +[`BitwiseCopyable`]: https://developer.apple.com/documentation/swift/bitwisecopyable +[`Copyable`]: https://developer.apple.com/documentation/swift/copyable +[`Sendable`]: https://developer.apple.com/documentation/swift/sendable + + + +For information about these protocols' requirements, +see the overview in their documentation. + +You use the same syntax to adopt these protocols +as you do to adopt other protocols. +The only difference is that you don't include +method or property declarations that implement the protocol's requirements. +For example: + +```swift +struct MyStruct: Copyable { + var counter = 12 +} + +extension MyStruct: BitwiseCopyable { } +``` + +The code above defines a new structure. +Because `Copyable` has only semantic requirements, +there isn't any code in the structure declaration to adopt the protocol. +Similarly, because `BitwiseCopyable` has only semantic requirements, +the extension that adopts that protocol has an empty body. + +You usually don't need to write conformance to these protocols --- +instead, Swift implicitly adds the conformance for you, +as described in . + + + ## Protocols as Types Protocols don't actually implement any functionality themselves. @@ -1368,6 +1427,96 @@ for level in levels.sorted() { ``` --> +## Implicit Conformance to a Protocol + +Some protocols are so common that you would write them +almost every time you declare a new type. +For the following protocols, +Swift automatically infers the conformance +when you define a type that implements the protocol's requirements, +so you don't have to write them yourself: + +- [`Copyable`][] +- [`Sendable`][] +- [`BitwiseCopyable`][] + + + +You can still write the conformance explicitly, +but it doesn't change how your code behaves. +To suppress an implicit conformance, +write a tilde (`~`) before the protocol name in the conformance list: + +```swift +struct FileDescriptor: ~Sendable { + let rawValue: Int +} +``` + + + +The code above shows part of a wrapper around POSIX file descriptors. +The `FileDescriptor` structure +satisfies all of the requirements of the `Sendable` protocol, +which normally makes it sendable. +However, +writing `~Sendable` suppresses this implicit conformance. +Even though file descriptors use integers +to identify and interact with open files, +and integer values are sendable, +making it nonsendable can help avoid certain kinds of bugs. + +Another way to suppress implicit conformance +is with an extension that you mark as unavailable: + +```swift +@available(*, unavailable) +extension FileDescriptor Sendable { } +``` + + + +When you write `~Sendable` in one place in your code, +as in the previous example, +code elsewhere in your program can still +extend the `FileDescriptor` type to add `Sendable` conformance. +In contrast, +the unavailable extension in this example +suppresses the implicit conformance to `Sendable` +and also prevents any extensions elsewhere in your code +from adding `Sendable` conformance to the type. + +> Note: +> In addition to the protocols discussed above, +> distributed actors implicitly conform to the [`Codable`][] protocol. + +[`Codable`]: https://developer.apple.com/documentation/swift/codable + ## Collections of Protocol Types A protocol can be used as the type to be stored in diff --git a/TSPL.docc/ReferenceManual/Declarations.md b/TSPL.docc/ReferenceManual/Declarations.md index 46274f0fd..0740d6b26 100644 --- a/TSPL.docc/ReferenceManual/Declarations.md +++ b/TSPL.docc/ReferenceManual/Declarations.md @@ -1069,6 +1069,8 @@ if you want more specific control, you can apply the `borrowing` or `consuming` parameter modifier. In this case, use `copy` to explicitly mark copy operations. +In addition, +values of a noncopyable type must be passed as either borrowing or consuming. Regardless of whether you use the default rules, Swift guarantees that object lifetime and