Fix SILGen's computation of default argument generator isolation

This commit is contained in:
John McCall
2025-09-09 14:08:49 -04:00
parent 4f6acbca63
commit 6f376c2468
4 changed files with 24 additions and 54 deletions

View File

@@ -38,6 +38,7 @@ namespace swift {
enum class EffectsKind : uint8_t;
class AbstractFunctionDecl;
class AbstractClosureExpr;
class ActorIsolation;
class ValueDecl;
class FuncDecl;
class ClosureExpr;
@@ -498,6 +499,8 @@ struct SILDeclRef {
return result;
}
ActorIsolation getActorIsolation() const;
/// True if the decl ref references a thunk from a natively foreign
/// declaration to Swift calling convention.
bool isForeignToNativeThunk() const;

View File

@@ -1873,3 +1873,21 @@ bool SILDeclRef::isCalleeAllocatedCoroutine() const {
return getASTContext().SILOpts.CoroutineAccessorsUseYieldOnce2;
}
ActorIsolation SILDeclRef::getActorIsolation() const {
// Deallocating destructor is always nonisolated. Isolation of the deinit
// applies only to isolated deallocator and destroyer.
if (kind == SILDeclRef::Kind::Deallocator) {
return ActorIsolation::forNonisolated(false);
}
// Default argument generators use the isolation of the initializer,
// not the general isolation of the function.
if (isDefaultArgGenerator()) {
auto param = getParameterAt(getDecl(), defaultArgIndex);
assert(param);
return param->getInitializerIsolation();
}
return getActorIsolationOfContext(getInnermostDeclContext());
}

View File

@@ -2419,32 +2419,7 @@ swift::getSILFunctionTypeActorIsolation(CanAnyFunctionType substFnInterfaceType,
}
if (constant) {
// TODO: It should to be possible to `getActorIsolation` if
// reference is to a decl instead of trying to get isolation
// from the reference kind, the attributes, or the context.
if (constant->kind == SILDeclRef::Kind::Deallocator) {
return ActorIsolation::forNonisolated(false);
}
if (auto *decl = constant->getAbstractFunctionDecl()) {
if (auto *nonisolatedAttr =
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
if (nonisolatedAttr->isNonSending())
return ActorIsolation::forCallerIsolationInheriting();
}
if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
return ActorIsolation::forNonisolated(false /*unsafe*/);
}
}
if (auto *closure = constant->getAbstractClosureExpr()) {
if (auto isolation = closure->getActorIsolation())
return isolation;
}
return getActorIsolationOfContext(constant->getInnermostDeclContext());
return constant->getActorIsolation();
}
if (substFnInterfaceType->hasExtInfo() &&

View File

@@ -768,32 +768,6 @@ static bool isEmittedOnDemand(SILModule &M, SILDeclRef constant) {
return false;
}
static ActorIsolation getActorIsolationForFunction(SILFunction &fn) {
if (auto constant = fn.getDeclRef()) {
if (constant.kind == SILDeclRef::Kind::Deallocator) {
// Deallocating destructor is always nonisolated. Isolation of the deinit
// applies only to isolated deallocator and destroyer.
return ActorIsolation::forNonisolated(false);
}
// If we have a closure expr, check if our type is
// nonisolated(nonsending). In that case, we use that instead.
if (auto *closureExpr = constant.getAbstractClosureExpr()) {
if (auto actorIsolation = closureExpr->getActorIsolation())
return actorIsolation;
}
// If we have actor isolation for our constant, put the isolation onto the
// function. If the isolation is unspecified, we do not return it.
if (auto isolation =
getActorIsolationOfContext(constant.getInnermostDeclContext()))
return isolation;
}
// Otherwise, return for unspecified.
return ActorIsolation::forUnspecified();
}
SILFunction *SILGenModule::getFunction(SILDeclRef constant,
ForDefinition_t forDefinition) {
// If we already emitted the function, return it.
@@ -820,7 +794,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
});
F->setDeclRef(constant);
F->setActorIsolation(getActorIsolationForFunction(*F));
F->setActorIsolation(constant.getActorIsolation());
assert(F && "SILFunction should have been defined");
@@ -1316,7 +1290,7 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
F->setDeclRef(constant);
// Set our actor isolation.
F->setActorIsolation(getActorIsolationForFunction(*F));
F->setActorIsolation(constant.getActorIsolation());
LLVM_DEBUG(llvm::dbgs() << "lowering ";
F->printName(llvm::dbgs());