Skip to content

Commit 87cfabc

Browse files
authored
Merge pull request #42229 from DougGregor/actor-isolation-rewrite
2 parents 27ad938 + fdc6260 commit 87cfabc

26 files changed

+1369
-1477
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ class ActorIsolation {
131131
return getKind() == GlobalActor || getKind() == GlobalActorUnsafe;
132132
}
133133

134+
bool isDistributedActor() const;
135+
134136
Type getGlobalActor() const {
135137
assert(isGlobalActor());
136138
return globalActor;

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4457,14 +4457,11 @@ NOTE(note_add_nonisolated_to_decl,none,
44574457
(DeclName, DescriptiveDeclKind))
44584458
NOTE(note_add_async_and_throws_to_decl,none,
44594459
"mark the protocol requirement %0 '%select{|async|throws|async throws}1' "
4460-
"in order witness it with 'distributed' function declared in distributed actor %2",
4461-
(DeclName, unsigned, DeclName))
4460+
"to allow actor-isolated conformances",
4461+
(DeclName, unsigned))
44624462
NOTE(note_add_distributed_to_decl,none,
4463-
"add 'distributed' to %0 to make this %1 witness the protocol requirement",
4463+
"add 'distributed' to %0 to make this %1 satisfy the protocol requirement",
44644464
(DeclName, DescriptiveDeclKind))
4465-
NOTE(note_distributed_requirement_defined_here,none,
4466-
"distributed instance method requirement %0 declared here",
4467-
(DeclName))
44684465
NOTE(note_add_globalactor_to_function,none,
44694466
"add '@%0' to make %1 %2 part of global actor %3",
44704467
(StringRef, DescriptiveDeclKind, DeclName, Type))
@@ -4541,13 +4538,16 @@ ERROR(override_implicit_unowned_executor,none,
45414538
"cannot override an actor's 'unownedExecutor' property that wasn't "
45424539
"explicitly defined", ())
45434540
ERROR(actor_isolated_non_self_reference,none,
4544-
"actor-isolated %0 %1 can not be "
4541+
"%5 %0 %1 can not be "
45454542
"%select{referenced|mutated|used 'inout'}2 "
4546-
"%select{on a non-isolated actor instance|"
4543+
"%select{from outside the actor|on a different actor instance|"
4544+
"on a non-isolated actor instance|"
45474545
"from a Sendable function|from a Sendable closure|"
45484546
"from an 'async let' initializer|from global actor %4|"
4549-
"from the main actor|from a non-isolated context|from a non-isolated autoclosure}3",
4550-
(DescriptiveDeclKind, DeclName, unsigned, unsigned, Type))
4547+
"from the main actor|from a non-isolated context|"
4548+
"from a non-isolated autoclosure}3",
4549+
(DescriptiveDeclKind, DeclName, unsigned, unsigned, Type,
4550+
ActorIsolation))
45514551
ERROR(distributed_actor_isolated_non_self_reference,none,
45524552
"distributed actor-isolated %0 %1 can not be accessed from a "
45534553
"non-isolated context",
@@ -4562,18 +4562,6 @@ ERROR(actor_isolated_inout_state,none,
45624562
ERROR(actor_isolated_mutating_func,none,
45634563
"cannot call mutating async function %0 on actor-isolated %1 %2",
45644564
(DeclName, DescriptiveDeclKind, DeclName))
4565-
ERROR(global_actor_from_instance_actor_context,none,
4566-
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
4567-
" from actor %3 %select{|in a synchronous context}5",
4568-
(DescriptiveDeclKind, DeclName, Type, DeclName, unsigned, bool))
4569-
ERROR(global_actor_from_other_global_actor_context,none,
4570-
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
4571-
" from different global actor %3 %select{|in a synchronous context}5",
4572-
(DescriptiveDeclKind, DeclName, Type, Type, unsigned, bool))
4573-
ERROR(global_actor_from_nonactor_context,none,
4574-
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
4575-
" from %select{this|a non-isolated}3%select{| synchronous}5 context",
4576-
(DescriptiveDeclKind, DeclName, Type, bool, unsigned, bool))
45774565
ERROR(actor_isolated_call,none,
45784566
"call to %0 function in a synchronous %1 context",
45794567
(ActorIsolation, ActorIsolation))
@@ -4667,19 +4655,9 @@ WARNING(shared_mutable_state_access,none,
46674655
"reference to %0 %1 is not concurrency-safe because it involves "
46684656
"shared mutable state", (DescriptiveDeclKind, DeclName))
46694657
ERROR(actor_isolated_witness,none,
4670-
"actor-isolated %0 %1 cannot be used to satisfy a protocol requirement",
4671-
(DescriptiveDeclKind, DeclName))
4672-
ERROR(distributed_actor_isolated_witness,none,
4673-
"distributed actor-isolated %0 %1 cannot be used to satisfy a protocol requirement",
4674-
(DescriptiveDeclKind, DeclName))
4675-
ERROR(global_actor_isolated_witness,none,
4676-
"%0 %1 isolated to global actor %2 can not satisfy corresponding "
4677-
"requirement from protocol %3",
4678-
(DescriptiveDeclKind, DeclName, Type, Identifier))
4679-
ERROR(global_actor_isolated_requirement_witness_conflict,none,
4680-
"%0 %1 isolated to global actor %2 can not satisfy corresponding "
4681-
"requirement from protocol %3 isolated to global actor %4",
4682-
(DescriptiveDeclKind, DeclName, Type, Identifier, Type))
4658+
"%select{|distributed }0%1 %2 %3 cannot be used to satisfy %4 protocol "
4659+
"requirement",
4660+
(bool, ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))
46834661
ERROR(actor_cannot_conform_to_global_actor_protocol,none,
46844662
"actor %0 cannot conform to global actor isolated protocol %1",
46854663
(Type, Type))

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9380,3 +9380,7 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) {
93809380
else
93819381
out << "closure";
93829382
}
9383+
9384+
bool ActorIsolation::isDistributedActor() const {
9385+
return getKind() == ActorInstance && getActor()->isDistributedActor();
9386+
}

lib/Sema/CSApply.cpp

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7786,18 +7786,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
77867786
return ctorCall;
77877787
}
77887788

7789-
/// Determine whether this closure should be treated as Sendable.
7790-
static bool isSendableClosure(ConstraintSystem &cs,
7791-
const AbstractClosureExpr *closure) {
7792-
if (auto fnType = cs.getType(const_cast<AbstractClosureExpr *>(closure))
7793-
->getAs<FunctionType>()) {
7794-
if (fnType->isSendable())
7795-
return true;
7796-
}
7797-
7798-
return false;
7799-
}
7800-
78017789
bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78027790
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl());
78037791
if (!(FD && FD->isInstanceMember() && FD->isDistributed()))
@@ -7821,52 +7809,60 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78217809

78227810
// If this is a method reference on an potentially isolated
78237811
// actor then it cannot be a remote thunk.
7824-
if (isPotentiallyIsolatedActor(actor, [&](ParamDecl *P) {
7825-
return P->isIsolated() ||
7826-
llvm::is_contained(solution.isolatedParams, P);
7827-
}))
7828-
return false;
7829-
7830-
bool isInAsyncLetInitializer = target && target->isAsyncLetInitializer();
7831-
7832-
auto isActorInitOrDeInitContext = [&](const DeclContext *dc) {
7833-
return ::isActorInitOrDeInitContext(
7834-
dc, [&](const AbstractClosureExpr *closure) {
7835-
return isSendableClosure(cs, closure);
7836-
});
7837-
};
7838-
7839-
switch (ActorIsolationRestriction::forDeclaration(ref, dc)) {
7840-
case ActorIsolationRestriction::CrossActorSelf: {
7841-
// Not a thunk if it's used in actor init or de-init.
7842-
if (!isInAsyncLetInitializer && isActorInitOrDeInitContext(dc))
7843-
return false;
7812+
bool isPotentiallyIsolated = isPotentiallyIsolatedActor(
7813+
actor,
7814+
[&](ParamDecl *P) {
7815+
return P->isIsolated() ||
7816+
llvm::is_contained(solution.isolatedParams, P);
7817+
});
7818+
7819+
// Adjust the declaration context to the innermost context that is neither
7820+
// a local function nor a closure, so that the actor reference is checked
7821+
auto referenceDC = dc;
7822+
while (true) {
7823+
switch (referenceDC->getContextKind()) {
7824+
case DeclContextKind::AbstractClosureExpr:
7825+
case DeclContextKind::Initializer:
7826+
case DeclContextKind::SerializedLocal:
7827+
referenceDC = referenceDC->getParent();
7828+
continue;
78447829

7845-
// Here we know that the method could be used across actors
7846-
// and the actor it's used on is non-isolated, which means
7847-
// that it could be a thunk, so we have to be conservative
7848-
// about it.
7849-
return true;
7850-
}
7830+
case DeclContextKind::AbstractFunctionDecl:
7831+
case DeclContextKind::GenericTypeDecl:
7832+
case DeclContextKind::SubscriptDecl:
7833+
if (auto value = dyn_cast<ValueDecl>(referenceDC->getAsDecl())) {
7834+
if (value->isLocalCapture()) {
7835+
referenceDC = referenceDC->getParent();
7836+
continue;
7837+
}
7838+
}
7839+
break;
78517840

7852-
case ActorIsolationRestriction::ActorSelf: {
7853-
// An instance member of an actor can be referenced from an actor's
7854-
// designated initializer or deinitializer.
7855-
if (actor->isActorSelf() && !isInAsyncLetInitializer) {
7856-
if (auto *fn = isActorInitOrDeInitContext(dc)) {
7857-
if (!(isa<ConstructorDecl>(fn) &&
7858-
cast<ConstructorDecl>(fn)->isConvenienceInit()))
7859-
return false;
7860-
}
7841+
case DeclContextKind::EnumElementDecl:
7842+
case DeclContextKind::ExtensionDecl:
7843+
case DeclContextKind::FileUnit:
7844+
case DeclContextKind::Module:
7845+
case DeclContextKind::TopLevelCodeDecl:
7846+
break;
78617847
}
78627848

7863-
// Call on a non-isolated actor in async context requires
7864-
// implicit thunk.
7865-
return isInAsyncLetInitializer || cs.isAsynchronousContext(dc);
7849+
break;
78667850
}
78677851

7868-
default:
7852+
// Create a simple actor reference, assuming that we might be in a
7853+
// non-isolated context but knowing whether it's potentially isolated.
7854+
// We only care about the "distributed" flag.
7855+
ReferencedActor actorRef = ReferencedActor(
7856+
actor, isPotentiallyIsolated, ReferencedActor::NonIsolatedContext);
7857+
auto refResult = ActorReferenceResult::forReference(
7858+
ref, context->getLoc(), referenceDC, None, actorRef);
7859+
switch (refResult) {
7860+
case ActorReferenceResult::ExitsActorToNonisolated:
7861+
case ActorReferenceResult::SameConcurrencyDomain:
78697862
return false;
7863+
7864+
case ActorReferenceResult::EntersActor:
7865+
return refResult.options.contains(ActorReferenceResult::Flags::Distributed);
78707866
}
78717867
}
78727868

0 commit comments

Comments
 (0)