@@ -15,23 +15,28 @@ import _Concurrency
1515
1616// ==== Distributed Actor -----------------------------------------------------
1717
18-
19-
2018/// Common protocol to which all distributed actors conform implicitly.
2119///
2220/// The `DistributedActor` protocol generalizes over all distributed actor types.
2321/// Distributed actor types implicitly conform to this protocol.
2422///
25- /// It is not possible to conform to this protocol manually by any other type
26- /// than a `distributed actor`.
23+ /// It is not possible to conform to this protocol by any other declaration other than a `distributed actor`.
2724///
2825/// It is possible to require a type to conform to the
2926/// ``DistributedActor`` protocol by refining it with another protocol,
3027/// or by using a generic constraint.
3128///
29+ /// ## Synthesized properties
30+ /// For every concrete distributed actor declaration, the compiler synthesizes two properties: `actorSystem` and `id`.
31+ /// They witness the ``actorSystem`` and ``id`` protocol requirements of the ``DistributedActor`` protocol.
32+ ///
33+ /// It is not possible to implement these properties explicitly in user code.
34+ /// These properties are `nonisolated` and accessible even if the instance is _remote_,
35+ /// because _all_ distributed actor references must store the actor system remote calls
36+ /// will be delivered through, as well as the id identifying the target of those calls.
3237///
3338/// ## The ActorSystem associated type
34- /// Every distributed actor must declare what type of distributed actor system
39+ /// Every distributed actor must declare what type of actor system
3540/// it is part of by implementing the ``ActorSystem`` associated type requirement.
3641///
3742/// This causes a number of other properties of the actor to be inferred:
@@ -98,12 +103,12 @@ import _Concurrency
98103/// because distributed actors are always managed by a concrete
99104/// distributed actor system and cannot exist on their own without one.
100105///
101- /// It is possible to explicitly declare an parameter-free initializer (`init()`),
106+ /// It is possible to explicitly declare a parameter-free initializer (`init()`),
102107/// however the `actorSystem` property still must be assigned a concrete actor
103108/// system instance the actor shall be part of.
104109///
105110/// In general it is recommended to always have an `actorSystem` parameter as
106- /// the last non-defaulted non-closure parameter in every distributed actors
111+ /// the last non-defaulted non-closure parameter in every actor's
107112/// initializer parameter list. This way it is simple to swap in a "test actor
108113/// system" instance in unit tests, and avoid relying on global state which could
109114/// make testing more difficult.
@@ -114,9 +119,10 @@ import _Concurrency
114119///
115120/// ### Property: Actor System
116121/// The ``actorSystem`` property is an important part of every distributed actor's lifecycle management.
117- /// Both initialization as well as de-initialization require interactions with the actor system,
118- /// and it is the actor system that delivers
119122///
123+ /// Both initialization as well as de-initialization require interactions with the actor system,
124+ /// and it is the actor system that handles all remote interactions of an actor, by both sending
125+ /// or receiving remote calls made on the actor.
120126///
121127/// The ``actorSystem`` property must be assigned in every designated initializer
122128/// of a distributed actor explicitly. It is highly recommended to make it a
@@ -130,11 +136,23 @@ import _Concurrency
130136/// }
131137/// ```
132138///
139+ /// Forgetting to initialize the actor system, will result in a compile time error:
140+ ///
141+ /// ```swift
142+ /// // BAD
143+ /// init(name: String, actorSystem: Self.ActorSystem) {
144+ /// self.name = name
145+ /// // BAD, will cause compile-time error; the `actorSystem` was not initialized.
146+ /// }
147+ /// ```
148+ ///
133149/// ### Property: Distributed Actor Identity
134150/// ``id`` is assigned by the actor system during the distributed actor's
135151/// initialization, and cannot be set or mutated by the actor itself.
136152///
137- /// ``id`` is the effective identity of the actor, and is used in equality checks.
153+ /// ``id`` is the effective identity of the actor, and is used in equality checks,
154+ /// as well as the actor's synthesized ``Codable`` conformance if the ``ID`` type
155+ /// conforms to ``Codable``.
138156///
139157/// ## Automatic Conformances
140158///
@@ -153,22 +171,26 @@ import _Concurrency
153171/// only `nonisolated` `id` and `actorSystem` properties are accessible for their
154172/// implementations.
155173///
156- /// ### Implicit ` Codable` conformance
157- /// If created with an actor system whose `ActorID` is `Codable`, the
174+ /// ### Implicit Codable conformance
175+ /// If created with an actor system whose ``DistributedActorSystem/ ActorID`` is `` Codable` `, the
158176/// compiler will synthesize code for the concrete distributed actor to conform
159- /// to `Codable` as well.
177+ /// to `` Codable` ` as well.
160178///
161179/// This is necessary to support distributed calls where the `SerializationRequirement`
162- /// is `Codable` and thus users may want to pass actors as arguments to remote calls.
180+ /// is `` Codable` ` and thus users may want to pass actors as arguments to remote calls.
163181///
164- /// The synthesized implementations use a single `SingleValueContainer` to
165- /// encode/decode the `self.id` property of the actor. The `Decoder` required
166- /// `init(from:)` is implemented by retrieving an actor system from the
167- /// decoders' `userInfo`, effectively like this:
168- /// `decoder.userInfo[.actorSystemKey] as? ActorSystem`. The obtained actor
169- /// system is then used to `resolve(id:using:)` the decoded ID.
182+ /// The synthesized implementations use a single ``SingleValueEncodingContainer`` to
183+ /// encode/decode the ``id`` property of the actor. The ``Decoder`` required
184+ /// ``Decoder/init(from:)`` is implemented by retrieving an actor system from the
185+ /// decoders' `userInfo`, effectively like as follows:
170186///
171- /// Use the `CodingUserInfoKey.actorSystemKey` to provide the necessary
187+ /// ```swift
188+ /// decoder.userInfo[.actorSystemKey] as? ActorSystem
189+ // ```
190+ ///
191+ /// The such obtained actor system is then used to ``resolve(id:using:)`` the decoded ``ID``.
192+ ///
193+ /// Use the ``CodingUserInfoKey/actorSystemKey`` to provide the necessary
172194/// actor system for the decoding initializer when decoding a distributed actor.
173195///
174196/// - SeeAlso: ``DistributedActorSystem``
@@ -192,17 +214,32 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable
192214 /// to return the same exact resolved actor instance, however all the references would
193215 /// represent logically references to the same distributed actor, e.g. on a different node.
194216 ///
195- /// Conformance to this requirement is synthesized automatically for any
196- /// `distributed actor` declaration.
217+ /// Depending on the capabilities of the actor system producing the identifiers,
218+ /// the `ID` may also be used to store instance specific metadata.
219+ ///
220+ /// ## Synthesized property
221+ ///
222+ /// In concrete distributed actor declarations, a witness for this protocol requirement is synthesized by the compiler.
223+ ///
224+ /// It is not possible to assign a value to the `id` directly; instead, it is assigned during an actors `init` (or `resolve`),
225+ /// by the managing actor system.
197226 nonisolated override var id : ID { get }
198227
199- /// The `ActorSystem` that is managing this distributed actor.
228+ /// The ``DistributedActorSystem`` that is managing this distributed actor.
229+ ///
230+ /// It is immutable and equal to the system assigned during the distributed actor's local initializer
231+ /// (or to the system passed to the ``resolve(id:using:)`` static function).
200232 ///
201- /// It is immutable and equal to the system passed in the local/resolve
202- /// initializer.
233+ /// ## Synthesized property
203234 ///
204- /// Conformance to this requirement is synthesized automatically for any
205- /// `distributed actor` declaration.
235+ /// In concrete distributed actor declarations, a witness for this protocol requirement is synthesized by the compiler.
236+ ///
237+ /// It is required to assign an initial value to the `actorSystem` property inside a distributed actor's designated initializer.
238+ /// Semantically, it can be treated as a `let` declaration, that must be assigned in order to fully-initialize the instance.
239+ ///
240+ /// If a distributed actor declares no initializer, its default initializer will take the shape of `init(actorSystem:)`,
241+ /// and initialize this property using the passed ``DistributedActorSystem``. If any user-defined initializer exists,
242+ /// the default initializer is not synthesized, and all the user-defined initializers must take care to initialize this property.
206243 nonisolated var actorSystem : ActorSystem { get }
207244
208245 /// Resolves the passed in `id` against the `system`, returning
@@ -215,6 +252,8 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable
215252 /// the system, allowing it to take over the remote messaging with the
216253 /// remote actor instance.
217254 ///
255+ /// - Postcondition: upon successful return, the returned actor's ``id`` and ``actorSystem`` properties
256+ /// will be equal to the values passed as parameters to this method.
218257 /// - Parameter id: identity uniquely identifying a, potentially remote, actor in the system
219258 /// - Parameter system: `system` which should be used to resolve the `identity`, and be associated with the returned actor
220259 static func resolve( id: ID , using system: ActorSystem ) throws -> Self
@@ -226,11 +265,15 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable
226265extension DistributedActor {
227266
228267 /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``.
268+ ///
269+ /// For more details see the "Hashable and Identifiable conformance" section of ``DistributedActor``.
229270 nonisolated public func hash( into hasher: inout Hasher ) {
230271 self . id. hash ( into: & hasher)
231272 }
232273
233274 /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``.
275+ ///
276+ /// For more details see the "Hashable and Identifiable conformance" section of ``DistributedActor``.
234277 nonisolated public static func == ( lhs: Self , rhs: Self ) -> Bool {
235278 lhs. id == rhs. id
236279 }
@@ -245,7 +288,7 @@ extension CodingUserInfoKey {
245288 /// conform to ``DistributedActorSystem``.
246289 ///
247290 /// Forgetting to set this key will result in that initializer throwing, because
248- /// an actor system is required.
291+ /// an actor system is required in order to call ``DistributedActor/resolve(id:using:)`` using it .
249292 @available ( SwiftStdlib 5 . 7 , * )
250293 public static let actorSystemKey = CodingUserInfoKey ( rawValue: " $distributed_actor_system " ) !
251294}
@@ -315,9 +358,17 @@ extension DistributedActor {
315358
316359// ==== isRemote / isLocal -----------------------------------------------------
317360
361+ /// Verifies if the passed ``DistributedActor`` conforming type is a remote reference.
362+ /// Passing a type not conforming to ``DistributedActor`` may result in undefined behavior.
363+ ///
364+ /// Official API to perform this task is `whenLocal`.
318365@_silgen_name ( " swift_distributed_actor_is_remote " )
319366public func __isRemoteActor( _ actor : AnyObject ) -> Bool
320367
368+ /// Verifies if the passed ``DistributedActor`` conforming type is a local reference.
369+ /// Passing a type not conforming to ``DistributedActor`` may result in undefined behavior.
370+ ///
371+ /// Official API to perform this task is `whenLocal`.
321372public func __isLocalActor( _ actor : AnyObject ) -> Bool {
322373 return !__isRemoteActor( actor )
323374}
0 commit comments