Skip to content

Commit 774a94f

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

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
@@ -9222,12 +9222,11 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) {
92229222

92239223
case ClosureActorIsolation::ActorInstance: {
92249224
auto selfDecl = isolation.getActorInstance();
9225-
auto actorClass = selfDecl->getType()->getReferenceStorageReferent()
9226-
->getClassOrBoundGenericClass();
9227-
// FIXME: Doesn't work properly with generics #59356
9228-
assert(actorClass && "Bad closure actor isolation?");
9229-
return ActorIsolation::forActorInstance(actorClass)
9230-
.withPreconcurrency(isolation.preconcurrency());
9225+
auto actor = selfDecl->getType()->getReferenceStorageReferent()
9226+
->getAnyActor();
9227+
assert(actor && "Bad closure actor isolation?");
9228+
return ActorIsolation::forActorInstance(actor)
9229+
.withPreconcurrency(isolation.preconcurrency());
92319230
}
92329231
}
92339232
}

lib/AST/Type.cpp

Lines changed: 24 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -400,84 +400,51 @@ bool CanType::isTypeErasedGenericClassTypeImpl(CanType type) {
400400
return false;
401401
}
402402

403-
static bool archetypeConformsTo(ArchetypeType *archetype, KnownProtocolKind protocol) {
404-
auto &ctx = archetype->getASTContext();
405-
auto expectedProto = ctx.getProtocol(protocol);
406-
if (!expectedProto)
407-
return false;
408-
409-
for (auto proto : archetype->getConformsTo()) {
410-
if (proto == expectedProto || proto->inheritsFrom(expectedProto))
411-
return true;
412-
}
413-
414-
return false;
415-
}
416-
417-
bool TypeBase::isActorType() {
403+
NominalTypeDecl *TypeBase::getAnyActor() {
418404
// Nominal types: check whether the declaration is an actor.
419-
if (auto nominal = getAnyNominal())
420-
return nominal->isActor();
405+
if (auto nominal = getAnyNominal()) {
406+
if (nominal->isAnyActor())
407+
return nominal;
408+
}
421409

422410
// Archetypes check for conformance to Actor.
423411
if (auto archetype = getAs<ArchetypeType>()) {
424-
return archetypeConformsTo(archetype, KnownProtocolKind::Actor);
412+
for (auto proto : archetype->getConformsTo()) {
413+
if (proto->isAnyActor())
414+
return proto;
415+
}
416+
417+
return nullptr;
425418
}
426419

427420
// Existential types: check for Actor protocol.
428421
if (isExistentialType()) {
429-
auto actorProto = getASTContext().getProtocol(KnownProtocolKind::Actor);
430-
if (!actorProto)
431-
return false;
432-
433422
auto layout = getExistentialLayout();
434423
if (auto superclass = layout.getSuperclass()) {
435-
if (superclass->isActorType())
436-
return true;
424+
if (auto actor = superclass->getAnyActor())
425+
return actor;
437426
}
438427

439428
for (auto proto : layout.getProtocols()) {
440-
if (proto->isActor())
441-
return true;
429+
if (proto->isAnyActor())
430+
return proto;
442431
}
443432

444-
return false;
433+
return nullptr;
445434
}
446435

436+
return nullptr;
437+
}
438+
439+
bool TypeBase::isActorType() {
440+
if (auto actor = getAnyActor())
441+
return actor->isActor();
447442
return false;
448443
}
449444

450445
bool TypeBase::isDistributedActor() {
451-
// Nominal types: check whether the declaration is an actor.
452-
if (auto *nominal = getAnyNominal()) {
453-
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
454-
return classDecl->isDistributedActor();
455-
456-
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal))
457-
return false;
458-
}
459-
460-
// Archetypes check for conformance to DistributedActor.
461-
if (auto archetype = getAs<ArchetypeType>()) {
462-
return archetypeConformsTo(archetype, KnownProtocolKind::DistributedActor);
463-
}
464-
465-
// Existential types: check for DistributedActor protocol conformance.
466-
if (isExistentialType()) {
467-
auto actorProto = getASTContext().getDistributedActorDecl();
468-
if (!actorProto)
469-
return false;
470-
471-
// TODO(distributed): Inheritance is not yet supported.
472-
473-
auto layout = getExistentialLayout();
474-
return llvm::any_of(layout.getProtocols(),
475-
[&actorProto](ProtocolDecl *protocol) {
476-
return protocol == actorProto ||
477-
protocol->inheritsFrom(actorProto);
478-
});
479-
}
480-
446+
if (auto actor = getAnyActor())
447+
return actor->isDistributedActor();
481448
return false;
482449
}
483450

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)