Skip to content

Commit b519c07

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
1 parent 439afd6 commit b519c07

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
@@ -6269,10 +6269,12 @@ static InferredActorIsolation computeActorIsolation(Evaluator &evaluator,
62696269
if (isolationFromAttr && isolationFromAttr->getKind() ==
62706270
ActorIsolation::CallerIsolationInheriting) {
62716271
auto nonisolated = value->getAttrs().getAttribute<NonisolatedAttr>();
6272-
if (!nonisolated || !nonisolated->isNonSending())
6273-
value->getAttrs().add(new (ctx) NonisolatedAttr(
6274-
/*atLoc*/ {}, /*range=*/{}, NonIsolatedModifier::NonSending,
6275-
/*implicit=*/true));
6272+
// Replace `nonisolated` with `nonisolated(nonsending)`
6273+
if (!nonisolated || !nonisolated->isNonSending()) {
6274+
value->getAttrs().removeAttribute(nonisolated);
6275+
value->getAttrs().add(NonisolatedAttr::createImplicit(
6276+
ctx, NonIsolatedModifier::NonSending));
6277+
}
62766278
}
62776279

62786280
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)