Skip to content

Commit 1bfe5e9

Browse files
committed
[Concurrency] Look for explicit 'nonisolated' when getting isolation from protocol conformances.
1 parent be670da commit 1bfe5e9

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5184,13 +5184,26 @@ getIsolationFromConformances(NominalTypeDecl *nominal) {
51845184
}
51855185

51865186
auto *proto = conformance->getProtocol();
5187-
switch (auto protoIsolation = getActorIsolation(proto)) {
5187+
auto inferredIsolation = getInferredActorIsolation(proto);
5188+
auto protoIsolation = inferredIsolation.isolation;
5189+
switch (protoIsolation) {
51885190
case ActorIsolation::ActorInstance:
51895191
case ActorIsolation::Unspecified:
5190-
case ActorIsolation::Nonisolated:
51915192
case ActorIsolation::CallerIsolationInheriting:
51925193
case ActorIsolation::NonisolatedUnsafe:
51935194
break;
5195+
case ActorIsolation::Nonisolated:
5196+
if (inferredIsolation.source.kind == IsolationSource::Kind::Explicit) {
5197+
if (!foundIsolation) {
5198+
// We found an explicitly 'nonisolated' protocol.
5199+
foundIsolation = {
5200+
protoIsolation,
5201+
IsolationSource(proto, IsolationSource::Conformance)};
5202+
}
5203+
continue;
5204+
} else {
5205+
break;
5206+
}
51945207

51955208
case ActorIsolation::Erased:
51965209
llvm_unreachable("protocol cannot have erased isolation");

test/Concurrency/nonisolated_rules.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public struct PublicNonSendable {
6363
}
6464

6565

66-
nonisolated struct NonisolatedStruct: GloballyIsolated {
66+
nonisolated struct StructRemovesGlobalActor: GloballyIsolated {
6767
var x: NonSendable
6868
var y: Int = 1
6969

@@ -106,6 +106,32 @@ struct A: Refined {
106106
init(x: NonSendable) {
107107
self.x = x // okay
108108
}
109+
110+
init() {
111+
self.x = NonSendable()
112+
}
113+
114+
func f() {}
115+
}
116+
117+
@MainActor protocol ExplicitGlobalActor: Refined {}
118+
119+
struct IsolatedStruct: ExplicitGlobalActor {
120+
// expected-note@+2 {{main actor isolation inferred from conformance to protocol 'ExplicitGlobalActor'}}
121+
// expected-note@+1 {{calls to instance method 'g()' from outside of its actor context are implicitly asynchronous}}
122+
func g() {}
123+
}
124+
125+
struct NonisolatedStruct {
126+
func callF() {
127+
return A().f() // okay, 'A' is non-isolated.
128+
}
129+
130+
// expected-note@+1 {{add '@MainActor' to make instance method 'callG()' part of global actor 'MainActor'}}
131+
func callG() {
132+
// expected-error@+1{{call to main actor-isolated instance method 'g()' in a synchronous nonisolated context}}
133+
return IsolatedStruct().g()
134+
}
109135
}
110136

111137
// MARK: - Extensions

0 commit comments

Comments
 (0)