Skip to content

Commit 4fca62a

Browse files
simanerushxedin
authored andcommitted
[Concurrency] Look for explicit 'nonisolated' when getting isolation from protocol conformances.
1 parent 00aa22f commit 4fca62a

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
@@ -5257,13 +5257,26 @@ getIsolationFromConformances(NominalTypeDecl *nominal) {
52575257
}
52585258

52595259
auto *proto = conformance->getProtocol();
5260-
switch (auto protoIsolation = getActorIsolation(proto)) {
5260+
auto inferredIsolation = getInferredActorIsolation(proto);
5261+
auto protoIsolation = inferredIsolation.isolation;
5262+
switch (protoIsolation) {
52615263
case ActorIsolation::ActorInstance:
52625264
case ActorIsolation::Unspecified:
5263-
case ActorIsolation::Nonisolated:
52645265
case ActorIsolation::CallerIsolationInheriting:
52655266
case ActorIsolation::NonisolatedUnsafe:
52665267
break;
5268+
case ActorIsolation::Nonisolated:
5269+
if (inferredIsolation.source.kind == IsolationSource::Kind::Explicit) {
5270+
if (!foundIsolation) {
5271+
// We found an explicitly 'nonisolated' protocol.
5272+
foundIsolation = {
5273+
protoIsolation,
5274+
IsolationSource(proto, IsolationSource::Conformance)};
5275+
}
5276+
continue;
5277+
} else {
5278+
break;
5279+
}
52675280

52685281
case ActorIsolation::Erased:
52695282
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

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

109135
// MARK: - Extensions

0 commit comments

Comments
 (0)