Skip to content

Commit 4aacc1c

Browse files
committed
Make the actor identity type an associated type of ActorTransport
Eliminate the use of the type-erased `AnyActorIdentity` within the distributed actor protocol by exposing the identity type of an actor transport as an associated type, `Identity`, which is then used to refer to all actors that have that transport. Retain `AnyActorIdentity`, because it remains useful for type-erasing actor transports, especially as the `Identity` type for `AnyActorTransport`. For now, make it the default type of `Identity`: this helps smooth over the transition from use of `AnyActorIdentity`, but we might want to remove this to make use of the type-erased forms always opt-in.
1 parent f83775b commit 4aacc1c

8 files changed

+92
-29
lines changed

lib/SILGen/SILGenDistributed.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) {
252252
// ==== Prepare argument references
253253
// --- Parameter: identity
254254
SILArgument *identityArg = F.getArgument(0);
255-
assert(identityArg->getType().getASTType()->isEqual(C.getAnyActorIdentityType()));
256255

257256
// --- Parameter: transport
258257
SILArgument *transportArg = F.getArgument(1);

lib/Sema/DerivedConformanceDistributedActor.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ static FuncDecl *deriveDistributedActor_resolve(DerivedConformance &derived) {
6161
return param;
6262
};
6363

64-
auto addressType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();
64+
auto addressType = getDistributedActorIdentityType(decl);
6565
auto transportType = getDistributedActorTransportType(decl);
6666

67-
// (_ identity: AnyActorIdentity, using transport: ActorTransport)
67+
// (_ identity: Identity, using transport: ActorTransport)
6868
auto *params = ParameterList::create(
6969
C,
7070
/*LParenLoc=*/SourceLoc(),
@@ -77,7 +77,7 @@ static FuncDecl *deriveDistributedActor_resolve(DerivedConformance &derived) {
7777
// Func name: resolve(_:using:)
7878
DeclName name(C, C.Id_resolve, params);
7979

80-
// Expected type: (Self) -> (AnyActorIdentity, ActorTransport) throws -> (Self)
80+
// Expected type: (Self) -> (Identity, ActorTransport) throws -> (Self)
8181
auto *factoryDecl =
8282
FuncDecl::createImplicit(C, StaticSpellingKind::KeywordStatic,
8383
name, SourceLoc(),
@@ -105,9 +105,9 @@ static ValueDecl *deriveDistributedActor_id(DerivedConformance &derived) {
105105

106106
// ```
107107
// nonisolated
108-
// let id: AnyActorIdentity
108+
// let id: Identity
109109
// ```
110-
auto propertyType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();
110+
auto propertyType = getDistributedActorIdentityType(derived.Nominal);
111111

112112
VarDecl *propDecl;
113113
PatternBindingDecl *pbDecl;

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,36 @@ Type swift::getDistributedActorTransportType(NominalTypeDecl *actor) {
257257
auto conformance = module->lookupConformance(selfType, protocol);
258258
return conformance.getTypeWitnessByName(selfType, ctx.Id_Transport);
259259
}
260+
261+
Type swift::getDistributedActorIdentityType(NominalTypeDecl *actor) {
262+
assert(actor->isDistributedActor());
263+
auto &ctx = actor->getASTContext();
264+
265+
auto actorProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
266+
if (!actorProtocol)
267+
return ErrorType::get(ctx);
268+
269+
AssociatedTypeDecl *transportDecl =
270+
actorProtocol->getAssociatedType(ctx.Id_Transport);
271+
if (!transportDecl)
272+
return ErrorType::get(ctx);
273+
274+
auto transportProtocol = ctx.getProtocol(KnownProtocolKind::ActorTransport);
275+
if (!transportProtocol)
276+
return ErrorType::get(ctx);
277+
278+
AssociatedTypeDecl *identityDecl =
279+
transportProtocol->getAssociatedType(ctx.getIdentifier("Identity"));
280+
if (!identityDecl)
281+
return ErrorType::get(ctx);
282+
283+
auto module = actor->getParentModule();
284+
Type selfType = actor->getSelfInterfaceType();
285+
auto conformance = module->lookupConformance(selfType, actorProtocol);
286+
Type dependentType = actorProtocol->getSelfInterfaceType();
287+
dependentType = DependentMemberType::get(dependentType, transportDecl);
288+
dependentType = DependentMemberType::get(dependentType, identityDecl);
289+
return dependentType.subst(
290+
SubstitutionMap::getProtocolSubstitutions(
291+
actorProtocol, selfType, conformance));
292+
}

lib/Sema/TypeCheckDistributed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ bool checkDistributedFunction(FuncDecl *decl, bool diagnose);
4848
/// Determine the distributed actor transport type for the given actor.
4949
Type getDistributedActorTransportType(NominalTypeDecl *actor);
5050

51+
/// Determine the distributed actor identity type for the given actor.
52+
Type getDistributedActorIdentityType(NominalTypeDecl *actor);
53+
5154
/// Diagnose a distributed func declaration in a not-distributed actor protocol.
5255
void diagnoseDistributedFunctionInNonDistributedActorProtocol(
5356
const ProtocolDecl *proto, InFlightDiagnostic &diag);

stdlib/public/Distributed/ActorTransport.swift

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,20 @@ import _Concurrency
1515

1616
@available(SwiftStdlib 5.6, *)
1717
public protocol ActorTransport: Sendable {
18+
/// The identity used by actors that communicate via this transport
19+
associatedtype Identity: ActorIdentity = AnyActorIdentity
1820

1921
// ==== ---------------------------------------------------------------------
2022
// - MARK: Resolving actors by identity
2123

22-
/// Upon decoding of a `AnyActorIdentity` this function will be called
24+
/// Upon decoding of an `Identity` this function will be called
2325
/// on the transport that is set un the Decoder's `userInfo` at decoding time.
2426
/// This user info is to be set by the transport, as it receives messages and
2527
/// attempts decoding them. This way, messages received on a specific transport
2628
/// (which may be representing a connection, or general transport mechanism)
2729
/// is able to utilize local knowledge and type information about what kind of
2830
/// identity to attempt to decode.
29-
func decodeIdentity(from decoder: Decoder) throws -> AnyActorIdentity
31+
func decodeIdentity(from decoder: Decoder) throws -> Identity
3032

3133
/// Resolve a local or remote actor address to a real actor instance, or throw if unable to.
3234
/// The returned value is either a local actor or proxy to a remote actor.
@@ -48,7 +50,7 @@ public protocol ActorTransport: Sendable {
4850
///
4951
/// Detecting liveness of such remote actors shall be offered / by transport libraries
5052
/// by other means, such as "watching an actor for termination" or similar.
51-
func resolve<Act>(_ identity: AnyActorIdentity, as actorType: Act.Type) throws -> Act?
53+
func resolve<Act>(_ identity: Identity, as actorType: Act.Type) throws -> Act?
5254
where Act: DistributedActor
5355

5456
// ==== ---------------------------------------------------------------------
@@ -64,37 +66,63 @@ public protocol ActorTransport: Sendable {
6466
/// E.g. if an actor is created under address `addr1` then immediately invoking
6567
/// `transport.resolve(address: addr1, as: Greeter.self)` MUST return a reference
6668
/// to the same actor.
67-
func assignIdentity<Act>(_ actorType: Act.Type) -> AnyActorIdentity
69+
func assignIdentity<Act>(_ actorType: Act.Type) -> Identity
6870
where Act: DistributedActor
6971

7072
func actorReady<Act>(_ actor: Act)
7173
where Act: DistributedActor
7274

7375
/// Called during actor deinit/destroy.
74-
func resignIdentity(_ id: AnyActorIdentity)
76+
func resignIdentity(_ id: Identity)
77+
}
78+
79+
@available(SwiftStdlib 5.6, *)
80+
extension ActorTransport {
81+
/// Try to resolve based on a type-erased actor identity.
82+
func resolve<Act>(
83+
anyIdentity identity: AnyActorIdentity, as actorType: Act.Type
84+
) throws -> Act? where Act: DistributedActor {
85+
return try resolve(identity.underlying as! Identity, as: actorType)
86+
}
87+
88+
/// Try to resign based on a type-erased actor identity.
89+
func resignAnyIdentity(_ id: AnyActorIdentity) {
90+
resignIdentity(id.underlying as! Identity)
91+
}
92+
93+
func decodeAnyIdentity(from decoder: Decoder) throws -> AnyActorIdentity {
94+
AnyActorIdentity(try decodeIdentity(from: decoder))
95+
}
96+
97+
func assignAnyIdentity<Act>(_ actorType: Act.Type) -> AnyActorIdentity
98+
where Act: DistributedActor {
99+
return AnyActorIdentity(assignIdentity(actorType))
100+
}
75101
}
76102

77103
@available(SwiftStdlib 5.6, *)
78104
public struct AnyActorTransport: ActorTransport {
105+
public typealias Identity = AnyActorIdentity
106+
79107
let transport: ActorTransport
80108

81109
public init<Transport: ActorTransport>(_ transport: Transport) {
82110
self.transport = transport
83111
}
84112

85-
public func decodeIdentity(from decoder: Decoder) throws -> AnyActorIdentity {
86-
return try transport.decodeIdentity(from: decoder)
113+
public func decodeIdentity(from decoder: Decoder) throws -> Identity {
114+
return try transport.decodeAnyIdentity(from: decoder)
87115
}
88116

89117
public func resolve<Act>(
90-
_ identity: AnyActorIdentity, as actorType: Act.Type
118+
_ identity: Identity, as actorType: Act.Type
91119
) throws -> Act? where Act: DistributedActor {
92-
return try transport.resolve(identity, as: actorType)
120+
return try transport.resolve(anyIdentity: identity, as: actorType)
93121
}
94122

95-
public func assignIdentity<Act>(_ actorType: Act.Type) -> AnyActorIdentity
123+
public func assignIdentity<Act>(_ actorType: Act.Type) -> Identity
96124
where Act: DistributedActor {
97-
return transport.assignIdentity(actorType)
125+
return transport.assignAnyIdentity(actorType)
98126
}
99127

100128
public func actorReady<Act>(_ actor: Act)
@@ -103,8 +131,8 @@ public struct AnyActorTransport: ActorTransport {
103131
}
104132

105133
/// Called during actor deinit/destroy.
106-
public func resignIdentity(_ id: AnyActorIdentity) {
107-
transport.resignIdentity(id)
134+
public func resignIdentity(_ id: Identity) {
135+
transport.resignAnyIdentity(id)
108136
}
109137
}
110138

stdlib/public/Distributed/DistributedActor.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public protocol DistributedActor:
3939
/// The type of transport used to communicate with actors of this type.
4040
associatedtype Transport: ActorTransport
4141

42+
/// The type of identity used by the transport.
43+
typealias Identity = Transport.Identity
44+
4245
/// Resolves the passed in `identity` against the `transport`, returning
4346
/// either a local or remote actor reference.
4447
///
@@ -51,11 +54,7 @@ public protocol DistributedActor:
5154
///
5255
/// - Parameter identity: identity uniquely identifying a, potentially remote, actor in the system
5356
/// - Parameter transport: `transport` which should be used to resolve the `identity`, and be associated with the returned actor
54-
// FIXME: Partially blocked on SE-309, because then we can store ActorIdentity directly
55-
// We want to move to accepting a generic or existential identity here
56-
// static func resolve<Identity>(_ identity: Identity, using transport: ActorTransport)
57-
// throws -> Self where Identity: ActorIdentity
58-
static func resolve(_ identity: AnyActorIdentity, using transport: Transport)
57+
static func resolve(_ identity: Identity, using transport: Transport)
5958
throws -> Self
6059

6160
/// The `ActorTransport` associated with this actor.
@@ -77,7 +76,7 @@ public protocol DistributedActor:
7776
///
7877
/// Conformance to this requirement is synthesized automatically for any
7978
/// `distributed actor` declaration.
80-
nonisolated var id: AnyActorIdentity { get }
79+
nonisolated var id: Identity { get }
8180
}
8281

8382
// ==== Hashable conformance ---------------------------------------------------
@@ -109,7 +108,7 @@ extension DistributedActor {
109108
"in Decoder.userInfo, while decoding \(Self.self).")
110109
}
111110

112-
let id: AnyActorIdentity = try transport.decodeIdentity(from: decoder)
111+
let id: Identity = try transport.decodeIdentity(from: decoder)
113112
self = try Self.resolve(id, using: transport)
114113
}
115114

@@ -151,6 +150,7 @@ public protocol ActorIdentity: Sendable, Hashable, Codable {}
151150

152151
@available(SwiftStdlib 5.6, *)
153152
public struct AnyActorIdentity: ActorIdentity, @unchecked Sendable, CustomStringConvertible {
153+
// FIXME: This probably shouldn't be public
154154
public let underlying: Any
155155
@usableFromInline let _hashInto: (inout Hasher) -> ()
156156
@usableFromInline let _equalTo: (Any) -> Bool
@@ -186,7 +186,7 @@ public struct AnyActorIdentity: ActorIdentity, @unchecked Sendable, CustomString
186186
"ActorTransport not available under the decoder.userInfo")
187187
}
188188

189-
self = try transport.decodeIdentity(from: decoder)
189+
self = try transport.decodeAnyIdentity(from: decoder)
190190
}
191191

192192
public func encode(to encoder: Encoder) throws {

test/Distributed/SIL/distributed_actor_default_deinit_sil.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ distributed actor MyDistActor {
3232
// CHECK: [[LOCAL_BB]]:
3333
// CHECK: [[ID_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.id
3434
// CHECK: [[TPORT_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.actorTransport
35-
// CHECK: [[RESIGN:%[0-9]+]] = witness_method $AnyActorTransport, #ActorTransport.resignIdentity : <Self where Self : ActorTransport> (Self) -> (AnyActorIdentity) -> ()
35+
// CHECK: [[RESIGN:%[0-9]+]] = witness_method $AnyActorTransport, #ActorTransport.resignIdentity : <Self where Self : ActorTransport> (Self) -> (Self.Identity) -> ()
3636
// CHECK: apply [[RESIGN]]<AnyActorTransport>([[ID_REF]], [[TPORT_REF]])
3737
// CHECK: br [[CONTINUE:bb[0-9]+]]
3838

test/Distributed/SIL/distributed_actor_default_init_sil.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ distributed actor MyDistActor {
2222
// *** obtain an identity ***
2323
// CHECK: [[SELF_METATYPE:%[0-9]+]] = metatype $@thick MyDistActor.Type
2424
// CHECK: [[ID_STACK:%[0-9+]+]] = alloc_stack $AnyActorIdentity
25-
// CHECK: [[ASSIGN_ID_FN:%[0-9]+]] = witness_method $AnyActorTransport, #ActorTransport.assignIdentity : <Self where Self : ActorTransport><Act where Act : DistributedActor> (Self) -> (Act.Type) -> AnyActorIdentity
25+
// CHECK: [[ASSIGN_ID_FN:%[0-9]+]] = witness_method $AnyActorTransport, #ActorTransport.assignIdentity : <Self where Self : ActorTransport><Act where Act : DistributedActor> (Self) -> (Act.Type) -> Self.Identity
2626
// CHECK: = apply [[ASSIGN_ID_FN]]<AnyActorTransport, MyDistActor>([[ID_STACK]], [[SELF_METATYPE]], [[TPORT]])
2727
// *** save identity ***
2828
// CHECK: [[ID_FIELD:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.id

0 commit comments

Comments
 (0)