Skip to content

[region-isolation] Dont crash when processing global actor isolated init accessors. #74321

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
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
23 changes: 14 additions & 9 deletions lib/SILOptimizer/Utils/SILIsolationInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,26 +813,31 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
}
}

// Otherwise, see if we have an allocator decl ref. If we do and we have an
// actor instance isolation, then we know that we are actively just calling
// the initializer. To just make region isolation work, treat this as
// disconnected so we can construct the actor value. Users cannot write
// allocator functions so we just need to worry about compiler generated
// code. In the case of a non-actor, we can only have an allocator that is
// global actor isolated, so we will never hit this code path.
// Otherwise, see if we need to handle this isolation computation specially
// due to information from the decl ref if we have one.
if (auto declRef = fArg->getFunction()->getDeclRef()) {
// First check if we have an allocator decl ref. If we do and we have an
// actor instance isolation, then we know that we are actively just calling
// the initializer. To just make region isolation work, treat this as
// disconnected so we can construct the actor value. Users cannot write
// allocator functions so we just need to worry about compiler generated
// code. In the case of a non-actor, we can only have an allocator that is
// global actor isolated, so we will never hit this code path.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding an assertion for the "we will never hit this..." case?

if (declRef.kind == SILDeclRef::Kind::Allocator) {
if (fArg->getFunction()->getActorIsolation().isActorInstanceIsolated()) {
return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
}
}

// Then see if we have an init accessor that is isolated to an actor
// instance, but for which we have not actually passed self. In such a case,
// we need to pass in a "fake" ActorInstance that users know is a sentinel
// for the self value.
if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) {
if (declRef.getDecl()) {
if (functionIsolation.isActorInstanceIsolated() && declRef.getDecl()) {
if (auto *accessor =
dyn_cast_or_null<AccessorDecl>(declRef.getFuncDecl())) {
if (accessor->isInitAccessor()) {
assert(functionIsolation.isActorInstanceIsolated());
return SILIsolationInfo::getActorInstanceIsolated(
fArg, ActorInstance::getForActorAccessorInit(),
functionIsolation.getActor());
Expand Down
13 changes: 13 additions & 0 deletions test/Concurrency/transfernonsendable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,19 @@ func initAccessorTests() {
get { fatalError() }
set { fatalError() }
}

@MainActor
var third: NonSendableKlass
@MainActor
var fourth: NonSendableKlass? = nil {
@storageRestrictions(initializes: third)
init(initialValue) {
third = initialValue!
}

get { fatalError() }
set { fatalError() }
}
}
}

Expand Down