Skip to content

Commit c7cad4b

Browse files
committed
Add a function for querying the isolation of an Initializer.
1 parent 367520c commit c7cad4b

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
@@ -12076,7 +12076,6 @@ ActorIsolation swift::getActorIsolationOfContext(
1207612076
DeclContext *dc,
1207712077
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
1207812078
getClosureActorIsolation) {
12079-
auto &ctx = dc->getASTContext();
1208012079
auto dcToUse = dc;
1208112080

1208212081
// Defer bodies share the actor isolation of their enclosing context.
@@ -12091,44 +12090,79 @@ ActorIsolation swift::getActorIsolationOfContext(
1209112090
if (auto *vd = dyn_cast_or_null<ValueDecl>(dcToUse->getAsDecl()))
1209212091
return getActorIsolation(vd);
1209312092

12094-
// In the context of the initializing or default-value expression of a
12095-
// stored property:
12096-
// - For a static stored property, the isolation matches the VarDecl.
12097-
// Static properties are initialized upon first use, so the isolation
12098-
// of the initializer must match the isolation required to access the
12099-
// property.
12100-
// - For a field of a nominal type, the expression can require the same
12101-
// actor isolation as the field itself. That default expression may only
12102-
// be used from inits that meet the required isolation.
12103-
if (auto *var = dcToUse->getNonLocalVarDecl()) {
12104-
// If IsolatedDefaultValues are enabled, treat this context as having
12105-
// unspecified isolation. We'll compute the required isolation for
12106-
// the initializer and validate that it matches the isolation of the
12107-
// var itself in the DefaultInitializerIsolation request.
12108-
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
12109-
return ActorIsolation::forUnspecified();
12110-
12111-
return getActorIsolation(var);
12112-
}
12113-
1211412093
if (auto *closure = dyn_cast<AbstractClosureExpr>(dcToUse)) {
1211512094
return getClosureActorIsolation(closure);
1211612095
}
1211712096

12097+
if (auto *init = dyn_cast<Initializer>(dcToUse)) {
12098+
// FIXME: force default argument initializers to report a meaningless
12099+
// isolation in order to break a bunch of cycles with the way that
12100+
// isolation is computed for them.
12101+
return getActorIsolation(init, /*ignoreDefaultArguments*/ true);
12102+
}
12103+
1211812104
if (isa<TopLevelCodeDecl>(dcToUse)) {
12105+
auto &ctx = dc->getASTContext();
1211912106
if (dcToUse->isAsyncContext() ||
12120-
dcToUse->getASTContext().LangOpts.StrictConcurrencyLevel >=
12121-
StrictConcurrency::Complete) {
12122-
if (Type mainActor = dcToUse->getASTContext().getMainActorType())
12107+
ctx.LangOpts.StrictConcurrencyLevel >= StrictConcurrency::Complete) {
12108+
if (Type mainActor = ctx.getMainActorType())
1212312109
return ActorIsolation::forGlobalActor(mainActor)
12124-
.withPreconcurrency(
12125-
!dcToUse->getASTContext().isSwiftVersionAtLeast(6));
12110+
.withPreconcurrency(!ctx.isSwiftVersionAtLeast(6));
1212612111
}
1212712112
}
1212812113

1212912114
return ActorIsolation::forUnspecified();
1213012115
}
1213112116

12117+
ActorIsolation swift::getActorIsolation(Initializer *init,
12118+
bool ignoreDefaultArguments) {
12119+
switch (init->getInitializerKind()) {
12120+
case InitializerKind::PatternBinding:
12121+
// In the context of the initializing or default-value expression of a
12122+
// stored property:
12123+
// - For a static stored property, the isolation matches the VarDecl.
12124+
// Static properties are initialized upon first use, so the isolation
12125+
// of the initializer must match the isolation required to access the
12126+
// property.
12127+
// - For a field of a nominal type, the expression can require the same
12128+
// actor isolation as the field itself. That default expression may only
12129+
// be used from inits that meet the required isolation.
12130+
if (auto *var = init->getNonLocalVarDecl()) {
12131+
auto &ctx = var->getASTContext();
12132+
12133+
// If IsolatedDefaultValues are enabled, treat this context as having
12134+
// unspecified isolation. We'll compute the required isolation for
12135+
// the initializer and validate that it matches the isolation of the
12136+
// var itself in the DefaultInitializerIsolation request.
12137+
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
12138+
return ActorIsolation::forUnspecified();
12139+
12140+
return getActorIsolation(var);
12141+
}
12142+
12143+
return ActorIsolation::forUnspecified();
12144+
12145+
case InitializerKind::DefaultArgument: {
12146+
auto defArgInit = cast<DefaultArgumentInitializer>(init);
12147+
12148+
// A hack when used from getActorIsolationOfContext to maintain the
12149+
// current behavior and avoid request cycles.
12150+
if (ignoreDefaultArguments)
12151+
return ActorIsolation::forUnspecified();
12152+
12153+
auto fn = cast<ValueDecl>(defArgInit->getParent()->getAsDecl());
12154+
auto param = getParameterAt(fn, defArgInit->getIndex());
12155+
assert(param);
12156+
return param->getInitializerIsolation();
12157+
}
12158+
12159+
case InitializerKind::PropertyWrapper:
12160+
case InitializerKind::CustomAttribute:
12161+
return ActorIsolation::forUnspecified();
12162+
}
12163+
llvm_unreachable("bad initializer kind");
12164+
}
12165+
1213212166
bool swift::isSameActorIsolated(ValueDecl *value, DeclContext *dc) {
1213312167
auto valueIsolation = getActorIsolation(value);
1213412168
auto dcIsolation = getActorIsolationOfContext(dc);

0 commit comments

Comments
 (0)