Skip to content

Commit 7d0e2b5

Browse files
committed
[Concurrency] SE-0449: Implied conformances to nonisolated protocols make witnesses nonisolated
Even if the requirement is stated on an isolated protocol if the conformance is implied by a nonisolated one all of the requirements and witnesses should be nonisolated. (cherry picked from commit 06be7bd)
1 parent 6e24564 commit 7d0e2b5

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5156,6 +5156,11 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) {
51565156
std::tuple<ProtocolConformance *, ActorIsolation, ValueDecl *>;
51575157
SmallVector<IsolatedRequirement, 2> isolatedRequirements;
51585158
for (auto conformance : conformances) {
5159+
auto *implied =
5160+
conformance->getSourceKind() == ConformanceEntryKind::Implied
5161+
? conformance->getImplyingConformance()
5162+
: nullptr;
5163+
51595164
auto protocol = conformance->getProtocol();
51605165
for (auto found : protocol->lookupDirect(value->getName())) {
51615166
if (!isa<ProtocolDecl>(found->getDeclContext()))
@@ -5165,6 +5170,19 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) {
51655170
if (!requirement || isa<TypeDecl>(requirement))
51665171
continue;
51675172

5173+
// The conformance implied by an explicitly stated nonisolated protocol
5174+
// makes all of the requirements nonisolated.
5175+
if (implied &&
5176+
implied->getSourceKind() == ConformanceEntryKind::Explicit) {
5177+
auto protocol = implied->getProtocol();
5178+
if (protocol->getAttrs().hasAttribute<NonisolatedAttr>()) {
5179+
isolatedRequirements.push_back(IsolatedRequirement{
5180+
implied, ActorIsolation::forNonisolated(/*unsafe=*/false),
5181+
requirement});
5182+
continue;
5183+
}
5184+
}
5185+
51685186
auto requirementIsolation = getActorIsolation(requirement);
51695187
switch (requirementIsolation) {
51705188
case ActorIsolation::ActorInstance:

test/Concurrency/nonisolated_rules.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,27 @@ struct TestIsolated : NonisolatedWithMembers {
185185
}
186186
}
187187

188+
@MainActor
189+
protocol Root {
190+
func testRoot()
191+
}
192+
193+
nonisolated protocol Child : Root {
194+
func testChild()
195+
}
196+
197+
struct TestDifferentLevels : Child {
198+
func testRoot() {}
199+
func testChild() {}
200+
func testNonWitness() {}
201+
}
202+
203+
nonisolated func testRequirementsOnMultipleNestingLevels(t: TestDifferentLevels) {
204+
t.testRoot() // okay
205+
t.testChild() // okay
206+
t.testNonWitness() // okay
207+
}
208+
188209
// MARK: - Extensions
189210

190211
nonisolated extension GloballyIsolated {

0 commit comments

Comments
 (0)