mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Add a function for querying the isolation of an Initializer.
This commit is contained in:
@@ -28,6 +28,7 @@ class raw_ostream;
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
class DeclContext;
|
class DeclContext;
|
||||||
|
class Initializer;
|
||||||
class ModuleDecl;
|
class ModuleDecl;
|
||||||
class VarDecl;
|
class VarDecl;
|
||||||
class NominalTypeDecl;
|
class NominalTypeDecl;
|
||||||
@@ -434,6 +435,10 @@ InferredActorIsolation getInferredActorIsolation(ValueDecl *value);
|
|||||||
ActorIsolation
|
ActorIsolation
|
||||||
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);
|
__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE);
|
||||||
|
|
||||||
|
/// Determine how the given initialization context is isolated.
|
||||||
|
ActorIsolation getActorIsolation(Initializer *init,
|
||||||
|
bool ignoreDefaultArguments = false);
|
||||||
|
|
||||||
/// Determine how the given declaration context is isolated.
|
/// Determine how the given declaration context is isolated.
|
||||||
/// \p getClosureActorIsolation allows the specification of actor isolation for
|
/// \p getClosureActorIsolation allows the specification of actor isolation for
|
||||||
/// closures that haven't been saved been saved to the AST yet. This is useful
|
/// closures that haven't been saved been saved to the AST yet. This is useful
|
||||||
|
|||||||
@@ -12076,7 +12076,6 @@ ActorIsolation swift::getActorIsolationOfContext(
|
|||||||
DeclContext *dc,
|
DeclContext *dc,
|
||||||
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
|
llvm::function_ref<ActorIsolation(AbstractClosureExpr *)>
|
||||||
getClosureActorIsolation) {
|
getClosureActorIsolation) {
|
||||||
auto &ctx = dc->getASTContext();
|
|
||||||
auto dcToUse = dc;
|
auto dcToUse = dc;
|
||||||
|
|
||||||
// Defer bodies share the actor isolation of their enclosing context.
|
// Defer bodies share the actor isolation of their enclosing context.
|
||||||
@@ -12091,44 +12090,79 @@ ActorIsolation swift::getActorIsolationOfContext(
|
|||||||
if (auto *vd = dyn_cast_or_null<ValueDecl>(dcToUse->getAsDecl()))
|
if (auto *vd = dyn_cast_or_null<ValueDecl>(dcToUse->getAsDecl()))
|
||||||
return getActorIsolation(vd);
|
return getActorIsolation(vd);
|
||||||
|
|
||||||
// In the context of the initializing or default-value expression of a
|
|
||||||
// stored property:
|
|
||||||
// - For a static stored property, the isolation matches the VarDecl.
|
|
||||||
// Static properties are initialized upon first use, so the isolation
|
|
||||||
// of the initializer must match the isolation required to access the
|
|
||||||
// property.
|
|
||||||
// - For a field of a nominal type, the expression can require the same
|
|
||||||
// actor isolation as the field itself. That default expression may only
|
|
||||||
// be used from inits that meet the required isolation.
|
|
||||||
if (auto *var = dcToUse->getNonLocalVarDecl()) {
|
|
||||||
// If IsolatedDefaultValues are enabled, treat this context as having
|
|
||||||
// unspecified isolation. We'll compute the required isolation for
|
|
||||||
// the initializer and validate that it matches the isolation of the
|
|
||||||
// var itself in the DefaultInitializerIsolation request.
|
|
||||||
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
|
|
||||||
return ActorIsolation::forUnspecified();
|
|
||||||
|
|
||||||
return getActorIsolation(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto *closure = dyn_cast<AbstractClosureExpr>(dcToUse)) {
|
if (auto *closure = dyn_cast<AbstractClosureExpr>(dcToUse)) {
|
||||||
return getClosureActorIsolation(closure);
|
return getClosureActorIsolation(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto *init = dyn_cast<Initializer>(dcToUse)) {
|
||||||
|
// FIXME: force default argument initializers to report a meaningless
|
||||||
|
// isolation in order to break a bunch of cycles with the way that
|
||||||
|
// isolation is computed for them.
|
||||||
|
return getActorIsolation(init, /*ignoreDefaultArguments*/ true);
|
||||||
|
}
|
||||||
|
|
||||||
if (isa<TopLevelCodeDecl>(dcToUse)) {
|
if (isa<TopLevelCodeDecl>(dcToUse)) {
|
||||||
|
auto &ctx = dc->getASTContext();
|
||||||
if (dcToUse->isAsyncContext() ||
|
if (dcToUse->isAsyncContext() ||
|
||||||
dcToUse->getASTContext().LangOpts.StrictConcurrencyLevel >=
|
ctx.LangOpts.StrictConcurrencyLevel >= StrictConcurrency::Complete) {
|
||||||
StrictConcurrency::Complete) {
|
if (Type mainActor = ctx.getMainActorType())
|
||||||
if (Type mainActor = dcToUse->getASTContext().getMainActorType())
|
|
||||||
return ActorIsolation::forGlobalActor(mainActor)
|
return ActorIsolation::forGlobalActor(mainActor)
|
||||||
.withPreconcurrency(
|
.withPreconcurrency(!ctx.isSwiftVersionAtLeast(6));
|
||||||
!dcToUse->getASTContext().isSwiftVersionAtLeast(6));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActorIsolation::forUnspecified();
|
return ActorIsolation::forUnspecified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActorIsolation swift::getActorIsolation(Initializer *init,
|
||||||
|
bool ignoreDefaultArguments) {
|
||||||
|
switch (init->getInitializerKind()) {
|
||||||
|
case InitializerKind::PatternBinding:
|
||||||
|
// In the context of the initializing or default-value expression of a
|
||||||
|
// stored property:
|
||||||
|
// - For a static stored property, the isolation matches the VarDecl.
|
||||||
|
// Static properties are initialized upon first use, so the isolation
|
||||||
|
// of the initializer must match the isolation required to access the
|
||||||
|
// property.
|
||||||
|
// - For a field of a nominal type, the expression can require the same
|
||||||
|
// actor isolation as the field itself. That default expression may only
|
||||||
|
// be used from inits that meet the required isolation.
|
||||||
|
if (auto *var = init->getNonLocalVarDecl()) {
|
||||||
|
auto &ctx = var->getASTContext();
|
||||||
|
|
||||||
|
// If IsolatedDefaultValues are enabled, treat this context as having
|
||||||
|
// unspecified isolation. We'll compute the required isolation for
|
||||||
|
// the initializer and validate that it matches the isolation of the
|
||||||
|
// var itself in the DefaultInitializerIsolation request.
|
||||||
|
if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues))
|
||||||
|
return ActorIsolation::forUnspecified();
|
||||||
|
|
||||||
|
return getActorIsolation(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActorIsolation::forUnspecified();
|
||||||
|
|
||||||
|
case InitializerKind::DefaultArgument: {
|
||||||
|
auto defArgInit = cast<DefaultArgumentInitializer>(init);
|
||||||
|
|
||||||
|
// A hack when used from getActorIsolationOfContext to maintain the
|
||||||
|
// current behavior and avoid request cycles.
|
||||||
|
if (ignoreDefaultArguments)
|
||||||
|
return ActorIsolation::forUnspecified();
|
||||||
|
|
||||||
|
auto fn = cast<ValueDecl>(defArgInit->getParent()->getAsDecl());
|
||||||
|
auto param = getParameterAt(fn, defArgInit->getIndex());
|
||||||
|
assert(param);
|
||||||
|
return param->getInitializerIsolation();
|
||||||
|
}
|
||||||
|
|
||||||
|
case InitializerKind::PropertyWrapper:
|
||||||
|
case InitializerKind::CustomAttribute:
|
||||||
|
return ActorIsolation::forUnspecified();
|
||||||
|
}
|
||||||
|
llvm_unreachable("bad initializer kind");
|
||||||
|
}
|
||||||
|
|
||||||
bool swift::isSameActorIsolated(ValueDecl *value, DeclContext *dc) {
|
bool swift::isSameActorIsolated(ValueDecl *value, DeclContext *dc) {
|
||||||
auto valueIsolation = getActorIsolation(value);
|
auto valueIsolation = getActorIsolation(value);
|
||||||
auto dcIsolation = getActorIsolationOfContext(dc);
|
auto dcIsolation = getActorIsolationOfContext(dc);
|
||||||
|
|||||||
Reference in New Issue
Block a user