Skip to content

Commit

Permalink
[Concurrency] Look for explicit 'nonisolated' when getting isolation …
Browse files Browse the repository at this point in the history
…from protocol conformances.
  • Loading branch information
simanerush committed Mar 11, 2025
1 parent 38cbdf8 commit 5825021
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
17 changes: 15 additions & 2 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5021,13 +5021,26 @@ getIsolationFromConformances(NominalTypeDecl *nominal) {
}

auto *proto = conformance->getProtocol();
switch (auto protoIsolation = getActorIsolation(proto)) {
auto inferredIsolation = getInferredActorIsolation(proto);
auto protoIsolation = inferredIsolation.isolation;
switch (protoIsolation) {
case ActorIsolation::ActorInstance:
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::CallerIsolationInheriting:
case ActorIsolation::NonisolatedUnsafe:
break;
case ActorIsolation::Nonisolated:
if (inferredIsolation.source.kind == IsolationSource::Kind::Explicit) {
if (!foundIsolation) {
// We found an explicitly 'nonisolated' protocol.
foundIsolation = {
protoIsolation,
IsolationSource(proto, IsolationSource::Conformance)};
}
continue;
} else {
break;
}

case ActorIsolation::Erased:
llvm_unreachable("protocol cannot have erased isolation");
Expand Down
28 changes: 27 additions & 1 deletion test/Concurrency/nonisolated_rules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public struct PublicNonSendable {
}


nonisolated struct NonisolatedStruct: GloballyIsolated {
nonisolated struct StructRemovesGlobalActor: GloballyIsolated {
var x: NonSendable
var y: Int = 1

Expand Down Expand Up @@ -106,6 +106,32 @@ struct A: Refined {
init(x: NonSendable) {
self.x = x // okay
}

init() {
self.x = NonSendable()
}

func f() {}
}

@MainActor protocol ExplicitGlobalActor: Refined {}

struct IsolatedStruct: ExplicitGlobalActor {
// expected-note@+2 {{main actor isolation inferred from conformance to protocol 'ExplicitGlobalActor'}}
// expected-note@+1 {{calls to instance method 'g()' from outside of its actor context are implicitly asynchronous}}
func g() {}
}

struct NonisolatedStruct {
func callF() {
return A().f() // okay, 'A' is non-isolated.
}

// expected-note@+1 {{add '@MainActor' to make instance method 'callG()' part of global actor 'MainActor'}}
func callG() {
// expected-error@+1{{call to main actor-isolated instance method 'g()' in a synchronous nonisolated context}}
return IsolatedStruct().g()
}
}

// MARK: - Extensions
Expand Down

0 comments on commit 5825021

Please sign in to comment.