Skip to content

Commit df7cfbf

Browse files
committed
Add a function for querying the isolation of an Initializer.
1 parent a6c40c7 commit df7cfbf

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class raw_ostream;
2828

2929
namespace swift {
3030
class DeclContext;
31+
class Initializer;
3132
class ModuleDecl;
3233
class VarDecl;
3334
class NominalTypeDecl;
@@ -434,6 +435,10 @@ InferredActorIsolation getInferredActorIsolation(ValueDecl *value);
434435
ActorIsolation
435436
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);
436437

438+
/// Determine how the given initialization context is isolated.
439+
ActorIsolation getActorIsolation(Initializer *init,
440+
bool ignoreDefaultArguments = false);
441+
437442
/// Determine how the given declaration context is isolated.
438443
/// \p getClosureActorIsolation allows the specification of actor isolation for
439444
/// closures that haven't been saved been saved to the AST yet. This is useful

lib/AST/Decl.cpp

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12008,7 +12008,6 @@ ActorIsolation swift::getActorIsolationOfContext(
1200812008
DeclContext *dc,
1200912009
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
1201012010
getClosureActorIsolation) {
12011-
auto &ctx = dc->getASTContext();
1201212011
auto dcToUse = dc;
1201312012

1201412013
// Defer bodies share the actor isolation of their enclosing context.
@@ -12023,44 +12022,79 @@ ActorIsolation swift::getActorIsolationOfContext(
1202312022
if (auto *vd = dyn_cast_or_null<ValueDecl>(dcToUse->getAsDecl()))
1202412023
return getActorIsolation(vd);
1202512024

12026-
// In the context of the initializing or default-value expression of a
12027-
// stored property:
12028-
// - For a static stored property, the isolation matches the VarDecl.
12029-
// Static properties are initialized upon first use, so the isolation
12030-
// of the initializer must match the isolation required to access the
12031-
// property.
12032-
// - For a field of a nominal type, the expression can require the same
12033-
// actor isolation as the field itself. That default expression may only
12034-
// be used from inits that meet the required isolation.
12035-
if (auto *var = dcToUse->getNonLocalVarDecl()) {
12036-
// If IsolatedDefaultValues are enabled, treat this context as having
12037-
// unspecified isolation. We'll compute the required isolation for
12038-
// the initializer and validate that it matches the isolation of the
12039-
// var itself in the DefaultInitializerIsolation request.
12040-
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
12041-
return ActorIsolation::forUnspecified();
12042-
12043-
return getActorIsolation(var);
12044-
}
12045-
1204612025
if (auto *closure = dyn_cast<AbstractClosureExpr>(dcToUse)) {
1204712026
return getClosureActorIsolation(closure);
1204812027
}
1204912028

12029+
if (auto *init = dyn_cast<Initializer>(dcToUse)) {
12030+
// FIXME: force default argument initializers to report a meaningless
12031+
// isolation in order to break a bunch of cycles with the way that
12032+
// isolation is computed for them.
12033+
return getActorIsolation(init, /*ignoreDefaultArguments*/ true);
12034+
}
12035+
1205012036
if (isa<TopLevelCodeDecl>(dcToUse)) {
12037+
auto &ctx = dc->getASTContext();
1205112038
if (dcToUse->isAsyncContext() ||
12052-
dcToUse->getASTContext().LangOpts.StrictConcurrencyLevel >=
12053-
StrictConcurrency::Complete) {
12054-
if (Type mainActor = dcToUse->getASTContext().getMainActorType())
12039+
ctx.LangOpts.StrictConcurrencyLevel >= StrictConcurrency::Complete) {
12040+
if (Type mainActor = ctx.getMainActorType())
1205512041
return ActorIsolation::forGlobalActor(mainActor)
12056-
.withPreconcurrency(
12057-
!dcToUse->getASTContext().isSwiftVersionAtLeast(6));
12042+
.withPreconcurrency(!ctx.isSwiftVersionAtLeast(6));
1205812043
}
1205912044
}
1206012045

1206112046
return ActorIsolation::forUnspecified();
1206212047
}
1206312048

12049+
ActorIsolation swift::getActorIsolation(Initializer *init,
12050+
bool ignoreDefaultArguments) {
12051+
switch (init->getInitializerKind()) {
12052+
case InitializerKind::PatternBinding:
12053+
// In the context of the initializing or default-value expression of a
12054+
// stored property:
12055+
// - For a static stored property, the isolation matches the VarDecl.
12056+
// Static properties are initialized upon first use, so the isolation
12057+
// of the initializer must match the isolation required to access the
12058+
// property.
12059+
// - For a field of a nominal type, the expression can require the same
12060+
// actor isolation as the field itself. That default expression may only
12061+
// be used from inits that meet the required isolation.
12062+
if (auto *var = init->getNonLocalVarDecl()) {
12063+
auto &ctx = var->getASTContext();
12064+
12065+
// If IsolatedDefaultValues are enabled, treat this context as having
12066+
// unspecified isolation. We'll compute the required isolation for
12067+
// the initializer and validate that it matches the isolation of the
12068+
// var itself in the DefaultInitializerIsolation request.
12069+
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
12070+
return ActorIsolation::forUnspecified();
12071+
12072+
return getActorIsolation(var);
12073+
}
12074+
12075+
return ActorIsolation::forUnspecified();
12076+
12077+
case InitializerKind::DefaultArgument: {
12078+
auto defArgInit = cast<DefaultArgumentInitializer>(init);
12079+
12080+
// A hack when used from getActorIsolationOfContext to maintain the
12081+
// current behavior and avoid request cycles.
12082+
if (ignoreDefaultArguments)
12083+
return ActorIsolation::forUnspecified();
12084+
12085+
auto fn = cast<ValueDecl>(defArgInit->getParent()->getAsDecl());
12086+
auto param = getParameterAt(fn, defArgInit->getIndex());
12087+
assert(param);
12088+
return param->getInitializerIsolation();
12089+
}
12090+
12091+
case InitializerKind::PropertyWrapper:
12092+
case InitializerKind::CustomAttribute:
12093+
return ActorIsolation::forUnspecified();
12094+
}
12095+
llvm_unreachable("bad initializer kind");
12096+
}
12097+
1206412098
bool swift::isSameActorIsolated(ValueDecl *value, DeclContext *dc) {
1206512099
auto valueIsolation = getActorIsolation(value);
1206612100
auto dcIsolation = getActorIsolationOfContext(dc);

0 commit comments

Comments
 (0)