Skip to content

Commit 84f70f3

Browse files
committed
[Concurrency] Replace nonisolated with nonisolated(nonsending) when isolation is inferred
With `NonisolatedNonsendingByDefault` an explicit `nonisolated` attribute in declaration context is inferred to mean `nonisolated(nonsending)` and it should be printed as such in interface files and other places. The inference logic that did didn't remove the original attribute which meant that it would be printed twice i.e. `nonisolated nonisolated(nonsending) func test() async` which is incorrect and would fail swift interface validation. Resolves: rdar://155847011 (cherry picked from commit b519c07)
1 parent 234a415 commit 84f70f3

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6275,10 +6275,12 @@ static InferredActorIsolation computeActorIsolation(Evaluator &evaluator,
62756275
if (isolationFromAttr && isolationFromAttr->getKind() ==
62766276
ActorIsolation::CallerIsolationInheriting) {
62776277
auto nonisolated = value->getAttrs().getAttribute<NonisolatedAttr>();
6278-
if (!nonisolated || !nonisolated->isNonSending())
6279-
value->getAttrs().add(new (ctx) NonisolatedAttr(
6280-
/*atLoc*/ {}, /*range=*/{}, NonIsolatedModifier::NonSending,
6281-
/*implicit=*/true));
6278+
// Replace `nonisolated` with `nonisolated(nonsending)`
6279+
if (!nonisolated || !nonisolated->isNonSending()) {
6280+
value->getAttrs().removeAttribute(nonisolated);
6281+
value->getAttrs().add(NonisolatedAttr::createImplicit(
6282+
ctx, NonIsolatedModifier::NonSending));
6283+
}
62826284
}
62836285

62846286
if (auto *fd = dyn_cast<FuncDecl>(value)) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
5+
6+
/// Build the library A
7+
// RUN: %target-swift-frontend -emit-module %t/src/A.swift \
8+
// RUN: -module-name A -swift-version 6 -enable-library-evolution \
9+
// RUN: -enable-upcoming-feature NonisolatedNonsendingByDefault \
10+
// RUN: -emit-module-path %t/A.swiftmodule \
11+
// RUN: -emit-module-interface-path %t/A.swiftinterface
12+
13+
// RUN: %target-swift-typecheck-module-from-interface(%t/A.swiftinterface) -module-name A
14+
15+
// Build the client using module
16+
// RUN: %target-swift-emit-sil -verify -module-name Client -I %t %t/src/Client.swift | %FileCheck %t/src/Client.swift
17+
18+
// RUN: rm %t/A.swiftmodule
19+
20+
// Re-build the client using interface
21+
// RUN: %target-swift-emit-sil -verify -module-name Client -I %t %t/src/Client.swift | %FileCheck %t/src/Client.swift
22+
23+
//--- A.swift
24+
@MainActor
25+
26+
public final class Test {
27+
public nonisolated func test() async {}
28+
}
29+
30+
//--- Client.swift
31+
import A
32+
33+
// CHECK-LABEL: sil hidden @$s6Client4test1ty1A4TestC_tYaF : $@convention(thin) @async (@guaranteed Test) -> ()
34+
// CHECK: bb0([[SELF:%.*]] : $Test):
35+
// CHECK: [[MAIN_ACTOR_EXISTENTIAL:%.*]] = init_existential_ref %4 : $MainActor : $MainActor, $any Actor
36+
// CHECK: [[ANY_ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[MAIN_ACTOR_EXISTENTIAL]]
37+
// CHECK: [[TEST_METHOD:%.*]] = function_ref @$s1A4TestC4testyyYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed Test) -> ()
38+
// CHECK: apply [[TEST_METHOD]]([[ANY_ACTOR]], [[SELF]])
39+
// CHECK: } // end sil function '$s6Client4test1ty1A4TestC_tYaF'
40+
@MainActor
41+
func test(t: Test) async {
42+
await t.test() // Ok
43+
}

0 commit comments

Comments
 (0)