Skip to content

Commit 23d2b28

Browse files
authored
Merge pull request #75045 from gottesmm/releaes/6.0-rdar130980933
[6.0][region-isolation] When determining isolation from a class_method, check for global actor isolation first.
2 parents 5c8e8c1 + f2f07f3 commit 23d2b28

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
@@ -601,40 +601,55 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
601601
bool isNonIsolatedUnsafe = exprAnalysis.hasNonisolatedUnsafe();
602602
{
603603
auto isolation = swift::getActorIsolation(dre->getDecl());
604-
if (isolation.isActorIsolated() &&
605-
(isolation.getKind() != ActorIsolation::ActorInstance ||
606-
isolation.getActorInstanceParameter() == 0)) {
607-
if (cmi->getOperand()->getType().isAnyActor()) {
604+
605+
if (isolation.isActorIsolated()) {
606+
// Check if we have a global actor and handle it appropriately.
607+
if (isolation.getKind() == ActorIsolation::GlobalActor) {
608+
bool localNonIsolatedUnsafe =
609+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
610+
return SILIsolationInfo::getGlobalActorIsolated(
611+
cmi, isolation.getGlobalActor())
612+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
613+
}
614+
615+
// In this case, we have an actor instance that is self.
616+
if (isolation.getKind() != ActorIsolation::ActorInstance &&
617+
isolation.isActorInstanceForSelfParameter()) {
618+
bool localNonIsolatedUnsafe =
619+
isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe();
608620
return SILIsolationInfo::getActorInstanceIsolated(
609-
cmi, cmi->getOperand(),
610-
cmi->getOperand()
611-
->getType()
612-
.getNominalOrBoundGenericNominal());
621+
cmi, cmi->getOperand(),
622+
cmi->getOperand()
623+
->getType()
624+
.getNominalOrBoundGenericNominal())
625+
.withUnsafeNonIsolated(localNonIsolatedUnsafe);
613626
}
614-
return SILIsolationInfo::getGlobalActorIsolated(
615-
cmi, isolation.getGlobalActor());
616627
}
617-
618-
isNonIsolatedUnsafe |= isolation.isNonisolatedUnsafe();
619628
}
620629

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

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 {
@@ -1799,3 +1800,16 @@ actor FunctionWithSendableResultAndIsolationActor {
17991800
return ""
18001801
}
18011802
}
1803+
1804+
@MainActor
1805+
func testThatGlobalActorTakesPrecedenceOverActorIsolationOnMethods() async {
1806+
let a = MyActor()
1807+
let ns = NonSendableKlass()
1808+
1809+
// 'ns' should be main actor isolated since useKlassMainActor is @MainActor
1810+
// isolated. Previously we would let MyActor take precedence here...
1811+
a.useKlassMainActor(ns)
1812+
1813+
// Meaning we would get an error here.
1814+
Task { @MainActor in print(ns) }
1815+
}

0 commit comments

Comments
 (0)