Skip to content

[Concurrency] Remove ClosureActorIsolation. #68567

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 4 commits into from
Sep 17, 2023
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
52 changes: 26 additions & 26 deletions include/swift/AST/ActorIsolation.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,6 @@ class NominalTypeDecl;
class SubstitutionMap;
class AbstractFunctionDecl;
class AbstractClosureExpr;
class ClosureActorIsolation;

/// Trampoline for AbstractClosureExpr::getActorIsolation.
ClosureActorIsolation
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);

/// Returns a function reference to \c __AbstractClosureExpr_getActorIsolation.
/// This is needed so we can use it as a default argument for
/// \c getActorIsolationOfContext without knowing the layout of
/// \c ClosureActorIsolation.
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
_getRef__AbstractClosureExpr_getActorIsolation();

/// Determine whether the given types are (canonically) equal, declared here
/// to avoid having to include Types.h.
Expand Down Expand Up @@ -83,23 +71,28 @@ class ActorIsolation {

private:
union {
NominalTypeDecl *actor;
llvm::PointerUnion<NominalTypeDecl *, VarDecl *> actorInstance;
Type globalActor;
void *pointer;
};
unsigned kind : 3;
unsigned isolatedByPreconcurrency : 1;
unsigned parameterIndex : 28;

ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex)
: actor(actor), kind(kind), isolatedByPreconcurrency(false),
parameterIndex(parameterIndex) { }
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);

ActorIsolation(Kind kind, VarDecl *capturedActor);

ActorIsolation(Kind kind, Type globalActor)
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false),
parameterIndex(0) { }

public:
// No-argument constructor needed for DenseMap use in PostfixCompletion.cpp
explicit ActorIsolation(Kind kind = Unspecified)
: pointer(nullptr), kind(kind), isolatedByPreconcurrency(false),
parameterIndex(0) { }

static ActorIsolation forUnspecified() {
return ActorIsolation(Unspecified, nullptr);
}
Expand All @@ -117,6 +110,10 @@ class ActorIsolation {
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
}

static ActorIsolation forActorInstanceCapture(VarDecl *capturedActor) {
return ActorIsolation(ActorInstance, capturedActor);
}

static ActorIsolation forGlobalActor(Type globalActor, bool unsafe) {
return ActorIsolation(
unsafe ? GlobalActorUnsafe : GlobalActor, globalActor);
Expand Down Expand Up @@ -151,10 +148,9 @@ class ActorIsolation {
}
}

NominalTypeDecl *getActor() const {
assert(getKind() == ActorInstance);
return actor;
}
NominalTypeDecl *getActor() const;

VarDecl *getActorInstance() const;

bool isGlobalActor() const {
return getKind() == GlobalActor || getKind() == GlobalActorUnsafe;
Expand Down Expand Up @@ -200,7 +196,8 @@ class ActorIsolation {
return true;

case ActorInstance:
return lhs.actor == rhs.actor && lhs.parameterIndex == rhs.parameterIndex;
return (lhs.getActor() == rhs.getActor() &&
lhs.parameterIndex == rhs.parameterIndex);

case GlobalActor:
case GlobalActorUnsafe:
Expand All @@ -223,16 +220,19 @@ class ActorIsolation {
/// Determine how the given value declaration is isolated.
ActorIsolation getActorIsolation(ValueDecl *value);

/// Trampoline for AbstractClosureExpr::getActorIsolation.
ActorIsolation
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);

/// Determine how the given declaration context is isolated.
/// \p getClosureActorIsolation allows the specification of actor isolation for
/// closures that haven't been saved been saved to the AST yet. This is useful
/// for solver-based code completion which doesn't modify the AST but stores the
/// actor isolation of closures in the constraint system solution.
ActorIsolation getActorIsolationOfContext(
DeclContext *dc,
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
getClosureActorIsolation =
_getRef__AbstractClosureExpr_getActorIsolation());
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
getClosureActorIsolation = __AbstractClosureExpr_getActorIsolation);

/// Check if both the value, and context are isolated to the same actor.
bool isSameActorIsolated(ValueDecl *value, DeclContext *dc);
Expand All @@ -256,9 +256,9 @@ bool usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn);
/// \return true if it is safe to drop the global-actor qualifier.
bool safeToDropGlobalActor(
DeclContext *dc, Type globalActor, Type ty,
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
getClosureActorIsolation =
_getRef__AbstractClosureExpr_getActorIsolation());
__AbstractClosureExpr_getActorIsolation);

void simple_display(llvm::raw_ostream &out, const ActorIsolation &state);

Expand Down
97 changes: 7 additions & 90 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3777,92 +3777,6 @@ class SequenceExpr final : public Expr,
}
};

/// Actor isolation for a closure.
class ClosureActorIsolation {
public:
enum Kind {
/// The closure is not isolated to any actor.
Nonisolated,

/// The closure is tied to the actor instance described by the given
/// \c VarDecl*, which is the (captured) `self` of an actor.
ActorInstance,

/// The closure is tied to the global actor described by the given type.
GlobalActor,
};

private:
/// The actor to which this closure is isolated, plus a bit indicating
/// whether the isolation was imposed by a preconcurrency declaration.
///
/// There are three possible states for the pointer:
/// - NULL: The closure is independent of any actor.
/// - VarDecl*: The 'self' variable for the actor instance to which
/// this closure is isolated. It will always have a type that conforms
/// to the \c Actor protocol.
/// - Type: The type of the global actor on which
llvm::PointerIntPair<llvm::PointerUnion<VarDecl *, Type>, 1, bool> storage;

ClosureActorIsolation(VarDecl *selfDecl, bool preconcurrency)
: storage(selfDecl, preconcurrency) { }
ClosureActorIsolation(Type globalActorType, bool preconcurrency)
: storage(globalActorType, preconcurrency) { }

public:
ClosureActorIsolation(bool preconcurrency = false)
: storage(nullptr, preconcurrency) { }

static ClosureActorIsolation forNonisolated(bool preconcurrency) {
return ClosureActorIsolation(preconcurrency);
}

static ClosureActorIsolation forActorInstance(VarDecl *selfDecl,
bool preconcurrency) {
return ClosureActorIsolation(selfDecl, preconcurrency);
}

static ClosureActorIsolation forGlobalActor(Type globalActorType,
bool preconcurrency) {
return ClosureActorIsolation(globalActorType, preconcurrency);
}

/// Determine the kind of isolation.
Kind getKind() const {
if (storage.getPointer().isNull())
return Kind::Nonisolated;

if (storage.getPointer().is<VarDecl *>())
return Kind::ActorInstance;

return Kind::GlobalActor;
}

/// Whether the closure is isolated at all.
explicit operator bool() const {
return getKind() != Kind::Nonisolated;
}

/// Whether the closure is isolated at all.
operator Kind() const {
return getKind();
}

VarDecl *getActorInstance() const {
return storage.getPointer().dyn_cast<VarDecl *>();
}

Type getGlobalActor() const {
return storage.getPointer().dyn_cast<Type>();
}

bool preconcurrency() const {
return storage.getInt();
}

ActorIsolation getActorIsolation() const;
};

/// A base class for closure expressions.
class AbstractClosureExpr : public DeclContext, public Expr {
CaptureInfo Captures;
Expand All @@ -3871,14 +3785,15 @@ class AbstractClosureExpr : public DeclContext, public Expr {
ParameterList *parameterList;

/// Actor isolation of the closure.
ClosureActorIsolation actorIsolation;
ActorIsolation actorIsolation;

public:
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
DeclContext *Parent)
: DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
Expr(Kind, Implicit, FnType),
parameterList(nullptr) {
parameterList(nullptr),
actorIsolation(ActorIsolation::forUnspecified()) {
Bits.AbstractClosureExpr.Discriminator = InvalidDiscriminator;
}

Expand Down Expand Up @@ -3951,9 +3866,11 @@ class AbstractClosureExpr : public DeclContext, public Expr {
/// returns nullptr if the closure doesn't have a body
BraceStmt *getBody() const;

ClosureActorIsolation getActorIsolation() const { return actorIsolation; }
ActorIsolation getActorIsolation() const {
return actorIsolation;
}

void setActorIsolation(ClosureActorIsolation actorIsolation) {
void setActorIsolation(ActorIsolation actorIsolation) {
this->actorIsolation = actorIsolation;
}

Expand Down
4 changes: 2 additions & 2 deletions include/swift/IDE/CompletionLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
bool CanCurrDeclContextHandleAsync = false;
/// Actor isolations that were determined during constraint solving but that
/// haven't been saved to the AST.
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
ClosureActorIsolations;
bool HaveDot = false;
bool IsUnwrappedOptional = false;
Expand Down Expand Up @@ -253,7 +253,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
}

void setClosureActorIsolations(
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
ClosureActorIsolations) {
this->ClosureActorIsolations = ClosureActorIsolations;
}
Expand Down
2 changes: 1 addition & 1 deletion include/swift/IDE/PostfixCompletion.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {

/// Actor isolations that were determined during constraint solving but that
/// haven't been saved to the AST.
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
llvm::DenseMap<AbstractClosureExpr *, ActorIsolation>
ClosureActorIsolations;

/// Checks whether this result has the same \c BaseTy and \c BaseDecl as
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Sema/IDETypeChecking.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ namespace swift {
bool completionContextUsesConcurrencyFeatures(const DeclContext *dc);

/// Determine the isolation of a particular closure.
ClosureActorIsolation determineClosureActorIsolation(
ActorIsolation determineClosureActorIsolation(
AbstractClosureExpr *closure, llvm::function_ref<Type(Expr *)> getType,
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
getClosureActorIsolation);

/// If the capture list shadows any declarations using shorthand syntax, i.e.
Expand Down
8 changes: 5 additions & 3 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2688,15 +2688,17 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, StringRef>,
printField(E->getRawDiscriminator(), "discriminator", DiscriminatorColor);

switch (auto isolation = E->getActorIsolation()) {
case ClosureActorIsolation::Nonisolated:
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
break;

case ClosureActorIsolation::ActorInstance:
case ActorIsolation::ActorInstance:
printFieldQuoted(isolation.getActorInstance()->printRef(),
"actor_isolated", CapturesColor);
break;

case ClosureActorIsolation::GlobalActor:
case ActorIsolation::GlobalActor:
case ActorIsolation::GlobalActorUnsafe:
printFieldQuoted(isolation.getGlobalActor().getString(),
"global_actor_isolated", CapturesColor);
break;
Expand Down
39 changes: 34 additions & 5 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10306,11 +10306,13 @@ bool VarDecl::isSelfParamCaptureIsolated() const {

if (auto closure = dyn_cast<AbstractClosureExpr>(dc)) {
switch (auto isolation = closure->getActorIsolation()) {
case ClosureActorIsolation::Nonisolated:
case ClosureActorIsolation::GlobalActor:
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::GlobalActor:
case ActorIsolation::GlobalActorUnsafe:
return false;

case ClosureActorIsolation::ActorInstance:
case ActorIsolation::ActorInstance:
auto isolatedVar = isolation.getActorInstance();
return isolatedVar->isSelfParameter() ||
isolatedVar-isSelfParamCapture();
Expand All @@ -10333,7 +10335,7 @@ ActorIsolation swift::getActorIsolation(ValueDecl *value) {

ActorIsolation swift::getActorIsolationOfContext(
DeclContext *dc,
llvm::function_ref<ClosureActorIsolation(AbstractClosureExpr *)>
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
getClosureActorIsolation) {
auto dcToUse = dc;
// Defer bodies share actor isolation of their enclosing context.
Expand All @@ -10349,7 +10351,7 @@ ActorIsolation swift::getActorIsolationOfContext(
return getActorIsolation(var);

if (auto *closure = dyn_cast<AbstractClosureExpr>(dcToUse)) {
return getClosureActorIsolation(closure).getActorIsolation();
return getClosureActorIsolation(closure);
}

if (auto *tld = dyn_cast<TopLevelCodeDecl>(dcToUse)) {
Expand Down Expand Up @@ -10597,6 +10599,33 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) {
out << "closure";
}

ActorIsolation::ActorIsolation(Kind kind, NominalTypeDecl *actor,
unsigned parameterIndex)
: actorInstance(actor), kind(kind),
isolatedByPreconcurrency(false),
parameterIndex(parameterIndex) { }

ActorIsolation::ActorIsolation(Kind kind, VarDecl *capturedActor)
: actorInstance(capturedActor), kind(kind),
isolatedByPreconcurrency(false),
parameterIndex(0) { }

NominalTypeDecl *ActorIsolation::getActor() const {
assert(getKind() == ActorInstance);

if (auto *instance = actorInstance.dyn_cast<VarDecl *>()) {
return instance->getTypeInContext()
->getReferenceStorageReferent()->getAnyActor();
}

return actorInstance.get<NominalTypeDecl *>();
}

VarDecl *ActorIsolation::getActorInstance() const {
assert(getKind() == ActorInstance);
return actorInstance.dyn_cast<VarDecl *>();
}

bool ActorIsolation::isMainActor() const {
if (isGlobalActor()) {
if (auto *nominal = getGlobalActor()->getAnyNominal())
Expand Down
Loading