Skip to content

Commit f970ef7

Browse files
committed
Make sure we can dig out the (distributed) actor from an archetype.
Fixes #59356 / rdar://94976378. (cherry picked from commit 774a94f)
1 parent 2522809 commit f970ef7

File tree

5 files changed

+55
-73
lines changed

5 files changed

+55
-73
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
786786
/// Break an existential down into a set of constraints.
787787
ExistentialLayout getExistentialLayout();
788788

789+
/// If this is an actor or distributed type, get the nominal type declaration
790+
/// for the actor.
791+
NominalTypeDecl *getAnyActor();
792+
789793
/// Determines whether this type is an actor type.
790794
bool isActorType();
791795

lib/AST/Decl.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9152,12 +9152,11 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) {
91529152

91539153
case ClosureActorIsolation::ActorInstance: {
91549154
auto selfDecl = isolation.getActorInstance();
9155-
auto actorClass = selfDecl->getType()->getReferenceStorageReferent()
9156-
->getClassOrBoundGenericClass();
9157-
// FIXME: Doesn't work properly with generics #59356
9158-
assert(actorClass && "Bad closure actor isolation?");
9159-
return ActorIsolation::forActorInstance(actorClass)
9160-
.withPreconcurrency(isolation.preconcurrency());
9155+
auto actor = selfDecl->getType()->getReferenceStorageReferent()
9156+
->getAnyActor();
9157+
assert(actor && "Bad closure actor isolation?");
9158+
return ActorIsolation::forActorInstance(actor)
9159+
.withPreconcurrency(isolation.preconcurrency());
91619160
}
91629161
}
91639162
}

lib/AST/Type.cpp

Lines changed: 24 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -391,84 +391,51 @@ bool CanType::isTypeErasedGenericClassTypeImpl(CanType type) {
391391
return false;
392392
}
393393

394-
static bool archetypeConformsTo(ArchetypeType *archetype, KnownProtocolKind protocol) {
395-
auto &ctx = archetype->getASTContext();
396-
auto expectedProto = ctx.getProtocol(protocol);
397-
if (!expectedProto)
398-
return false;
399-
400-
for (auto proto : archetype->getConformsTo()) {
401-
if (proto == expectedProto || proto->inheritsFrom(expectedProto))
402-
return true;
403-
}
404-
405-
return false;
406-
}
407-
408-
bool TypeBase::isActorType() {
394+
NominalTypeDecl *TypeBase::getAnyActor() {
409395
// Nominal types: check whether the declaration is an actor.
410-
if (auto nominal = getAnyNominal())
411-
return nominal->isActor();
396+
if (auto nominal = getAnyNominal()) {
397+
if (nominal->isAnyActor())
398+
return nominal;
399+
}
412400

413401
// Archetypes check for conformance to Actor.
414402
if (auto archetype = getAs<ArchetypeType>()) {
415-
return archetypeConformsTo(archetype, KnownProtocolKind::Actor);
403+
for (auto proto : archetype->getConformsTo()) {
404+
if (proto->isAnyActor())
405+
return proto;
406+
}
407+
408+
return nullptr;
416409
}
417410

418411
// Existential types: check for Actor protocol.
419412
if (isExistentialType()) {
420-
auto actorProto = getASTContext().getProtocol(KnownProtocolKind::Actor);
421-
if (!actorProto)
422-
return false;
423-
424413
auto layout = getExistentialLayout();
425414
if (auto superclass = layout.getSuperclass()) {
426-
if (superclass->isActorType())
427-
return true;
415+
if (auto actor = superclass->getAnyActor())
416+
return actor;
428417
}
429418

430419
for (auto proto : layout.getProtocols()) {
431-
if (proto->isActor())
432-
return true;
420+
if (proto->isAnyActor())
421+
return proto;
433422
}
434423

435-
return false;
424+
return nullptr;
436425
}
437426

427+
return nullptr;
428+
}
429+
430+
bool TypeBase::isActorType() {
431+
if (auto actor = getAnyActor())
432+
return actor->isActor();
438433
return false;
439434
}
440435

441436
bool TypeBase::isDistributedActor() {
442-
// Nominal types: check whether the declaration is an actor.
443-
if (auto *nominal = getAnyNominal()) {
444-
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
445-
return classDecl->isDistributedActor();
446-
447-
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal))
448-
return false;
449-
}
450-
451-
// Archetypes check for conformance to DistributedActor.
452-
if (auto archetype = getAs<ArchetypeType>()) {
453-
return archetypeConformsTo(archetype, KnownProtocolKind::DistributedActor);
454-
}
455-
456-
// Existential types: check for DistributedActor protocol conformance.
457-
if (isExistentialType()) {
458-
auto actorProto = getASTContext().getDistributedActorDecl();
459-
if (!actorProto)
460-
return false;
461-
462-
// TODO(distributed): Inheritance is not yet supported.
463-
464-
auto layout = getExistentialLayout();
465-
return llvm::any_of(layout.getProtocols(),
466-
[&actorProto](ProtocolDecl *protocol) {
467-
return protocol == actorProto ||
468-
protocol->inheritsFrom(actorProto);
469-
});
470-
}
471-
437+
if (auto actor = getAnyActor())
438+
return actor->isDistributedActor();
472439
return false;
473440
}
474441

test/Distributed/distributed_protocol_isolation.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,10 @@ func test_watchingDA<WDA: TerminationWatchingDA>(da: WDA) async throws {
224224
// expected-warning@-2{{no calls to throwing functions occur within 'try' expression}}
225225

226226
let __secretlyKnownToBeLocal = da
227-
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK // FIXME(#59356): (the __secretlyKnown is a hack, but the whenLocal crashes now on pending isolation getting with generic actors for closures)
228-
// FIXME: pending fix of closure isolation checking with actors #59356
229-
// await da.whenLocal { __secretlyKnownToBeLocal in
230-
// await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
231-
// }
227+
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
228+
await da.whenLocal { __secretlyKnownToBeLocal in
229+
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
230+
}
232231
}
233232

234233
func test_watchingDA_erased(da: DA_TerminationWatchingDA) async throws {
@@ -238,11 +237,10 @@ func test_watchingDA_erased(da: DA_TerminationWatchingDA) async throws {
238237
// expected-warning@-2{{no calls to throwing functions occur within 'try' expression}}
239238

240239
let __secretlyKnownToBeLocal = wda
241-
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK // FIXME(#59356): (the __secretlyKnown is a hack, but the whenLocal crashes now on pending isolation getting with generic actors for closures)
242-
// FIXME: pending fix of closure isolation checking with actors #59356
243-
// await wda.whenLocal { __secretlyKnownToBeLocal in
244-
// await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
245-
// }
240+
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
241+
await wda.whenLocal { __secretlyKnownToBeLocal in
242+
await __secretlyKnownToBeLocal.terminated(da: "local calls are okey!") // OK
243+
}
246244
}
247245

248246
func test_watchingDA_any(da: any TerminationWatchingDA) async throws {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -typecheck %s
2+
3+
// REQUIRES: concurrency
4+
5+
@available(SwiftStdlib 5.1, *)
6+
extension Actor {
7+
func f() { }
8+
9+
func g(a: [Int]) {
10+
a.forEach { i in
11+
f()
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)