Skip to content

Commit 9f8e5e8

Browse files
authored
Merge pull request #75016 from gottesmm/pr-d4640c7e2919faea7bc7eb96ebd8af643108e2d8
[region-isolation] When determining isolation from a class_method, check for global actor isolation first.
2 parents bd2fcf3 + 0a06c00 commit 9f8e5e8

File tree

3 files changed

+57
-22
lines changed

3 files changed

+57
-22
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ class ActorIsolation {
180180
return parameterIndex;
181181
}
182182

183+
/// Returns true if this actor-instance isolation appllies to the self
184+
/// parameter of a method.
185+
bool isActorInstanceForSelfParameter() const {
186+
return getActorInstanceParameter() == 0;
187+
}
188+
183189
bool isSILParsed() const { return silParsed; }
184190

185191
bool isActorIsolated() const {

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -602,40 +602,55 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
602602
bool isNonIsolatedUnsafe = exprAnalysis.hasNonisolatedUnsafe();
603603
{
604604
auto isolation = swift::getActorIsolation(dre->getDecl());
605-
if (isolation.isActorIsolated() &&
606-
(isolation.getKind() != ActorIsolation::ActorInstance ||
607-
isolation.getActorInstanceParameter() == 0)) {
608-
if (cmi->getOperand()->getType().isAnyActor()) {
605+
606+
if (isolation.isActorIsolated()) {
607+
// Check if we have a global actor and handle it appropriately.
608+
if (isolation.getKind() == ActorIsolation::GlobalActor) {
609+
bool localNonIsolatedUnsafe =
610+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
611+
return SILIsolationInfo::getGlobalActorIsolated(
612+
cmi, isolation.getGlobalActor())
613+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
614+
}
615+
616+
// In this case, we have an actor instance that is self.
617+
if (isolation.getKind() != ActorIsolation::ActorInstance &&
618+
isolation.isActorInstanceForSelfParameter()) {
619+
bool localNonIsolatedUnsafe =
620+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
609621
return SILIsolationInfo::getActorInstanceIsolated(
610-
cmi, cmi->getOperand(),
611-
cmi->getOperand()
612-
->getType()
613-
.getNominalOrBoundGenericNominal());
622+
cmi, cmi->getOperand(),
623+
cmi->getOperand()
624+
->getType()
625+
.getNominalOrBoundGenericNominal())
626+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
614627
}
615-
return SILIsolationInfo::getGlobalActorIsolated(
616-
cmi, isolation.getGlobalActor());
617628
}
618-
619-
isNonIsolatedUnsafe |= isolation.isNonisolatedUnsafe();
620629
}
621630

622631
if (auto type = dre->getType()->getNominalOrBoundGenericNominal()) {
623632
if (auto isolation = swift::getActorIsolation(type)) {
624-
if (isolation.isActorIsolated() &&
625-
(isolation.getKind() != ActorIsolation::ActorInstance ||
626-
isolation.getActorInstanceParameter() == 0)) {
627-
if (cmi->getOperand()->getType().isAnyActor()) {
633+
if (isolation.isActorIsolated()) {
634+
// Check if we have a global actor and handle it appropriately.
635+
if (isolation.getKind() == ActorIsolation::GlobalActor) {
636+
bool localNonIsolatedUnsafe =
637+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
638+
return SILIsolationInfo::getGlobalActorIsolated(
639+
cmi, isolation.getGlobalActor())
640+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
641+
}
642+
643+
// In this case, we have an actor instance that is self.
644+
if (isolation.getKind() != ActorIsolation::ActorInstance &&
645+
isolation.isActorInstanceForSelfParameter()) {
646+
bool localNonIsolatedUnsafe =
647+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
628648
return SILIsolationInfo::getActorInstanceIsolated(
629649
cmi, cmi->getOperand(),
630650
cmi->getOperand()
631651
->getType()
632652
.getNominalOrBoundGenericNominal())
633-
.withUnsafeNonIsolated(isNonIsolatedUnsafe);
634-
}
635-
636-
if (auto globalIso = SILIsolationInfo::getGlobalActorIsolated(
637-
cmi, isolation.getGlobalActor())) {
638-
return globalIso.withUnsafeNonIsolated(isNonIsolatedUnsafe);
653+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
639654
}
640655
}
641656
}

test/Concurrency/transfernonsendable.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ actor MyActor {
4040
func useSendableFunction(_: @Sendable () -> Void) {}
4141
func useNonSendableFunction(_: () -> Void) {}
4242
func doSomething() {}
43+
@MainActor func useKlassMainActor(_ x: NonSendableKlass) {}
4344
}
4445

4546
final actor FinalActor {
@@ -1809,3 +1810,16 @@ actor FunctionWithSendableResultAndIsolationActor {
18091810
return ""
18101811
}
18111812
}
1813+
1814+
@MainActor
1815+
func testThatGlobalActorTakesPrecedenceOverActorIsolationOnMethods() async {
1816+
let a = MyActor()
1817+
let ns = NonSendableKlass()
1818+
1819+
// 'ns' should be main actor isolated since useKlassMainActor is @MainActor
1820+
// isolated. Previously we would let MyActor take precedence here...
1821+
a.useKlassMainActor(ns)
1822+
1823+
// Meaning we would get an error here.
1824+
Task { @MainActor in print(ns) }
1825+
}

0 commit comments

Comments
 (0)