Skip to content

Commit 0a70ec0

Browse files
authored
Merge pull request #82041 from DougGregor/sendable-metatype-docs-6.2
2 parents c9d5e4b + cef7f42 commit 0a70ec0

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

stdlib/public/core/Sendable.swift

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,55 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
/// A type `T` whose metatype `T.Type` is `Sendable`.
13+
/// A type whose metatype can be shared across arbitrary concurrent contexts
14+
/// without introducing a risk of data races. When a generic type `T` conforms
15+
/// to `SendableMetatype`, its metatype `T.Type` conforms to `Sendable`. All
16+
/// concrete types implicitly conform to the `SendableMetatype` protocol, so its
17+
/// primary purpose is in generic code to prohibit the use of isolated
18+
/// conformances along with the generic type.
19+
///
20+
/// A generic type `T` will need a `SendableMetatype` conformance when its
21+
/// metatype is shared across concurrency boundaries. For example,
22+
///
23+
/// protocol P {
24+
/// static func f()
25+
/// }
26+
///
27+
/// func useFromAnotherTask<T: P>(_: T.Type) {
28+
/// Task { @concurrent in
29+
/// T.f() // error: capturing non-Sendable type `T.Type` in a concurrently-executing task
30+
/// }
31+
/// }
32+
///
33+
/// The potential data race above would occur when `useFromAnotherTask` is
34+
/// provided with an isolated conformance to `P`. For example:
35+
///
36+
/// @MainActor
37+
/// class MyModel: @MainActor P {
38+
/// /*implicitly @MainActor/*
39+
/// static func f() {
40+
/// /* on the main actor */
41+
/// }
42+
/// }
43+
///
44+
/// useFromAnotherTask(MyModel.self)
45+
///
46+
/// Here, the error within the body of `useFromAnotherTask` is preventing the
47+
/// isolated conformance from leaving the current task and actor. The signature
48+
/// of `useFromAnotherTask` can be adjusted to introduce a requirement on
49+
/// `SendableMetatype`:
50+
///
51+
/// func useFromAnotherTask<T: P & SendableMetatype>(_: T.Type) {
52+
/// Task { @concurrent in
53+
/// T.f() // error: okay, T.Type is Sendable
54+
/// }
55+
/// }
56+
///
57+
/// useFromAnotherTask(MyModel.self) // error: cannot use main-actor-isolated conformance `MyModel: P` for a `SendableMetatype`-conforming type parameter `T`
58+
///
59+
/// The `Sendable` protocol inherits from `SendableMetatype`, so any generic
60+
/// type `T` with a requirement `T: Sendable` will have the implied requirement
61+
/// `T: SendableMetatype`.
1462
@_marker public protocol SendableMetatype: ~Copyable, ~Escapable { }
1563

1664
/// A thread-safe type whose values can be shared across arbitrary concurrent
@@ -135,6 +183,9 @@
135183
/// ### Sendable Metatypes
136184
///
137185
/// Metatypes such as `Int.Type` implicitly conform to the `Sendable` protocol.
186+
/// For a generic type `T`, its metatype `T.Type` does not necessarily conform
187+
/// to `Sendable`. Please see the `SendableMetatype` protocol for more
188+
/// information.
138189
@_marker public protocol Sendable: SendableMetatype, ~Copyable, ~Escapable { }
139190

140191
///

0 commit comments

Comments
 (0)