Skip to content

Distributed actor isolation #39558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions docs/ReferenceGuides/UnderscoredAttributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,6 @@ library), instead of at an arbitrary point in time.
For more details, see the forum post on
[dynamic method replacement](https://forums.swift.org/t/dynamic-method-replacement/16619).

## `@_distributedActorIndependent`

Marks a specific property of a distributed actor to be available even if the
actor is remote.

This only applies to two distributed actor properties `address` and `transport`.
It cannot be safely declared on any properties defined by ordinary Swift code.

## `@_effects(effectname)`

Tells the compiler that the implementation of the defined function is limited
Expand Down
7 changes: 1 addition & 6 deletions include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -658,12 +658,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor,
APIBreakingToAdd | APIBreakingToRemove,
118)

SIMPLE_DECL_ATTR(_distributedActorIndependent, DistributedActorIndependent,
OnFunc | OnVar |
DistributedOnly | UserInaccessible |
ABIStableToAdd | ABIStableToRemove |
APIBreakingToAdd | APIBreakingToRemove,
119)
// 119 is unused

SIMPLE_DECL_ATTR(_assemblyVision, EmitAssemblyVisionRemarks,
OnFunc | UserInaccessible | NotSerialized | OnNominalType |
Expand Down
4 changes: 0 additions & 4 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2391,8 +2391,6 @@ class ValueDecl : public Decl {
/// Is this declaration marked with 'dynamic'?
bool isDynamic() const;

bool isDistributedActorIndependent() const;

private:
bool isObjCDynamic() const {
return isObjC() && isDynamic();
Expand Down Expand Up @@ -4790,8 +4788,6 @@ class AbstractStorageDecl : public ValueDecl {

bool hasAnyNativeDynamicAccessors() const;

bool isDistributedActorIndependent() const;

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4616,9 +4616,6 @@ ERROR(distributed_actor_user_defined_special_property,none,
"property %0 cannot be defined explicitly, as it conflicts with "
"distributed actor synthesized stored property",
(DeclName))
ERROR(distributed_actor_independent_property_must_be_let,none,
"_distributedActorIndependent can be applied to properties, however they must be 'let'",
())
NOTE(distributed_actor_isolated_property,none,
"distributed actor state is only available within the actor instance", // TODO: reword in terms of isolation
())
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4338,6 +4338,7 @@ class ApplyExpr : public Expr {
Bits.ApplyExpr.ImplicitlyAsync = false;
Bits.ApplyExpr.ImplicitlyThrows = false;
Bits.ApplyExpr.NoAsync = false;
Bits.ApplyExpr.ShouldApplyDistributedThunk = false;
}

public:
Expand Down
8 changes: 0 additions & 8 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2934,10 +2934,6 @@ bool ValueDecl::isDynamic() const {
getAttrs().hasAttribute<DynamicAttr>());
}

bool ValueDecl::isDistributedActorIndependent() const {
return getAttrs().hasAttribute<DistributedActorIndependentAttr>();
}

bool ValueDecl::isObjCDynamicInGenericClass() const {
if (!isObjCDynamic())
return false;
Expand Down Expand Up @@ -5371,10 +5367,6 @@ bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const {
return false;
}

bool AbstractStorageDecl::isDistributedActorIndependent() const {
return getAttrs().hasAttribute<DistributedActorIndependentAttr>();
}

void AbstractStorageDecl::setAccessors(SourceLoc lbraceLoc,
ArrayRef<AccessorDecl *> accessors,
SourceLoc rbraceLoc) {
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenDistributed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ void SILGenFunction::emitDistributedActorClassMemberDestruction(
B.emitBlock(remoteMemberDestroyBB);

for (VarDecl *vd : cd->getStoredProperties()) {
if (!vd->getAttrs().hasAttribute<DistributedActorIndependentAttr>())
if (getActorIsolation(vd) == ActorIsolation::DistributedActorInstance)
continue;

destroyClassMember(cleanupLoc, selfValue, vd);
Expand Down
5 changes: 2 additions & 3 deletions lib/Sema/CodeSynthesisDistributedActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,8 @@ AbstractFunctionDecl *TypeChecker::addImplicitDistributedActorRemoteFunction(
remoteFuncDecl->getAttrs().add(
new (C) DynamicAttr(/*implicit=*/true));

// @_distributedActorIndependent
remoteFuncDecl->getAttrs().add(
new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true));
// nonisolated
remoteFuncDecl->getAttrs().add(new (C) NonisolatedAttr(/*IsImplicit=*/true));

// users should never have to access this function directly;
// it is only invoked from our distributed function thunk if the actor is remote.
Expand Down
12 changes: 6 additions & 6 deletions lib/Sema/DerivedConformanceDistributedActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static ValueDecl *deriveDistributedActor_id(DerivedConformance &derived) {
auto &C = derived.Context;

// ```
// @_distributedActorIndependent
// nonisolated
// let id: AnyActorIdentity
// ```
auto propertyType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();
Expand All @@ -119,9 +119,9 @@ static ValueDecl *deriveDistributedActor_id(DerivedConformance &derived) {

propDecl->setIntroducer(VarDecl::Introducer::Let);

// mark as @_distributedActorIndependent, allowing access to it from everywhere
// mark as nonisolated, allowing access to it from everywhere
propDecl->getAttrs().add(
new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true));
new (C) NonisolatedAttr(/*IsImplicit=*/true));

derived.addMembersToConformanceContext({ propDecl, pbDecl });
return propDecl;
Expand All @@ -133,7 +133,7 @@ static ValueDecl *deriveDistributedActor_actorTransport(
auto &C = derived.Context;

// ```
// @_distributedActorIndependent
// nonisolated
// let actorTransport: ActorTransport
// ```
// (no need for @actorIndependent because it is an immutable let)
Expand All @@ -148,9 +148,9 @@ static ValueDecl *deriveDistributedActor_actorTransport(

propDecl->setIntroducer(VarDecl::Introducer::Let);

// mark as @_distributedActorIndependent, allowing access to it from everywhere
// mark as nonisolated, allowing access to it from everywhere
propDecl->getAttrs().add(
new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true));
new (C) NonisolatedAttr(/*IsImplicit=*/true));

derived.addMembersToConformanceContext({ propDecl, pbDecl });
return propDecl;
Expand Down
21 changes: 8 additions & 13 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {

void visitActorAttr(ActorAttr *attr);
void visitDistributedActorAttr(DistributedActorAttr *attr);
void visitDistributedActorIndependentAttr(DistributedActorIndependentAttr *attr);
void visitGlobalActorAttr(GlobalActorAttr *attr);
void visitAsyncAttr(AsyncAttr *attr);
void visitMarkerAttr(MarkerAttr *attr);
Expand Down Expand Up @@ -5400,7 +5399,7 @@ void AttributeChecker::visitActorAttr(ActorAttr *attr) {
void AttributeChecker::visitDistributedActorAttr(DistributedActorAttr *attr) {
auto dc = D->getDeclContext();

// distributed can be applied to actor class definitions and async functions
// distributed can be applied to actor definitions and their methods
if (auto varDecl = dyn_cast<VarDecl>(D)) {
// distributed can not be applied to stored properties
diagnoseAndRemoveAttr(attr, diag::distributed_actor_property);
Expand Down Expand Up @@ -5473,7 +5472,13 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
// distributed actors. Attempts of nonisolated access would be
// cross-actor, and that means they might be accessing on a remote actor,
// in which case the stored property storage does not exist.
if (nominal && nominal->isDistributedActor()) {
//
// The synthesized "id" and "actorTransport" are the only exceptions,
// because the implementation mirrors them.
if (nominal && nominal->isDistributedActor() &&
!(var->isImplicit() &&
(var->getName() == Ctx.Id_id ||
var->getName() == Ctx.Id_actorTransport))) {
diagnoseAndRemoveAttr(attr,
diag::nonisolated_distributed_actor_storage);
return;
Expand Down Expand Up @@ -5504,16 +5509,6 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
}
}

void AttributeChecker::visitDistributedActorIndependentAttr(DistributedActorIndependentAttr *attr) {
/// user-inaccessible _distributedActorIndependent can only be applied to let properties
if (auto var = dyn_cast<VarDecl>(D)) {
if (!var->isLet()) {
diagnoseAndRemoveAttr(attr, diag::distributed_actor_independent_property_must_be_let);
return;
}
}
}

void AttributeChecker::visitGlobalActorAttr(GlobalActorAttr *attr) {
auto nominal = dyn_cast<NominalTypeDecl>(D);
if (!nominal)
Expand Down
Loading