Skip to content

Commit b0d2ca9

Browse files
committed
[Concurrency] Fix nonisolated(nonsending) interaction with #isolation
1 parent 677b897 commit b0d2ca9

File tree

3 files changed

+100
-8
lines changed

3 files changed

+100
-8
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7295,15 +7295,30 @@ RValue RValueEmitter::visitMacroExpansionExpr(MacroExpansionExpr *E,
72957295

72967296
RValue RValueEmitter::visitCurrentContextIsolationExpr(
72977297
CurrentContextIsolationExpr *E, SGFContext C) {
7298-
// If we are in an actor initializer that is isolated to self, the
7299-
// current isolation is flow-sensitive; use that instead of the
7300-
// synthesized expression.
7301-
if (auto ctor = dyn_cast_or_null<ConstructorDecl>(
7302-
SGF.F.getDeclRef().getDecl())) {
7303-
auto isolation = getActorIsolation(ctor);
7304-
if (ctor->isDesignatedInit() &&
7298+
auto afd =
7299+
dyn_cast_or_null<AbstractFunctionDecl>(SGF.F.getDeclRef().getDecl());
7300+
if (afd) {
7301+
auto isolation = getActorIsolation(afd);
7302+
if (isolation == ActorIsolation::CallerIsolationInheriting) {
7303+
auto *isolatedArg = SGF.F.maybeGetIsolatedArgument();
7304+
assert(isolatedArg &&
7305+
"Caller Isolation Inheriting without isolated parameter");
7306+
ManagedValue isolatedMV;
7307+
if (isolatedArg->getOwnershipKind() == OwnershipKind::Guaranteed) {
7308+
isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
7309+
} else {
7310+
isolatedMV = ManagedValue::forUnmanagedOwnedValue(isolatedArg);
7311+
}
7312+
return RValue(SGF, E, isolatedMV);
7313+
}
7314+
7315+
auto ctor = dyn_cast_or_null<ConstructorDecl>(afd);
7316+
if (ctor && ctor->isDesignatedInit() &&
73057317
isolation == ActorIsolation::ActorInstance &&
73067318
isolation.getActorInstance() == ctor->getImplicitSelfDecl()) {
7319+
// If we are in an actor initializer that is isolated to self, the
7320+
// current isolation is flow-sensitive; use that instead of the
7321+
// synthesized expression.
73077322
auto isolationValue =
73087323
SGF.emitFlowSensitiveSelfIsolation(E, isolation);
73097324
return RValue(SGF, E, isolationValue);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4384,10 +4384,15 @@ namespace {
43844384

43854385
case ActorIsolation::Unspecified:
43864386
case ActorIsolation::Nonisolated:
4387-
case ActorIsolation::CallerIsolationInheriting:
43884387
case ActorIsolation::NonisolatedUnsafe:
43894388
actorExpr = new (ctx) NilLiteralExpr(loc, /*implicit=*/false);
43904389
break;
4390+
case ActorIsolation::CallerIsolationInheriting:
4391+
// For caller isolation this expression will be replaced in SILGen
4392+
// because we're adding an implicit isolated parameter that #isolated
4393+
// must resolve to, but cannot do so during AST expansion quite yet.
4394+
actorExpr = new (ctx) NilLiteralExpr(loc, /*implicit=*/false);
4395+
break;
43914396
}
43924397

43934398

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) | %FileCheck %s --dump-input=always
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: executable_test
5+
// REQUIRES: concurrency_runtime
6+
7+
// rdar://78109470
8+
// UNSUPPORTED: back_deployment_runtime
9+
// UNSUPPORTED: freestanding
10+
11+
import _Concurrency
12+
import StdlibUnittest
13+
14+
@main struct Main {
15+
static func main() async {
16+
await explicitIsolatedParam()
17+
// CHECK: go - explicitIsolatedParam
18+
// CHECK: outerIsolation = #isolation = Optional(Swift.MainActor)
19+
// CHECK: Task{} #isolation = nil
20+
// CHECK: Task{ [outerIsolation] } outerIsolation = Optional(Swift.MainActor), #iso = Optional(Swift.MainActor)
21+
// CHECK: done - explicitIsolatedParam
22+
23+
print()
24+
await nonisolatedNonsending()
25+
// CHECK: go - nonisolatedNonsending
26+
// CHECK: outerIsolation = #isolation = Optional(Swift.MainActor)
27+
// CHECK: Task{} #isolation = nil
28+
// CHECK: Task{ [outerIsolation] } outerIsolation = Optional(Swift.MainActor), #iso = nil
29+
// CHECK: done - nonisolatedNonsending
30+
}
31+
}
32+
33+
func explicitIsolatedParam(isolation: isolated (any Actor)? = #isolation) async {
34+
print("go - \(#function)")
35+
MainActor.assertIsolated()
36+
37+
let outerIsolation = #isolation
38+
print("outerIsolation = #isolation = \(String(describing: outerIsolation))")
39+
40+
await Task {
41+
let iso = #isolation
42+
print("Task{} #isolation = \(String(describing: iso))")
43+
}.value
44+
45+
await Task {
46+
let iso = #isolation
47+
print("Task{ [outerIsolation] } outerIsolation = \(String(describing: isolation)), #iso = \(String(describing: iso))")
48+
}.value
49+
50+
print("done - \(#function)")
51+
}
52+
53+
54+
nonisolated(nonsending) func nonisolatedNonsending() async {
55+
print("go - \(#function)")
56+
MainActor.assertIsolated()
57+
58+
let outerIsolation = #isolation
59+
print("outerIsolation = #isolation = \(String(describing: outerIsolation))") // WRONG; this is nil today
60+
61+
await Task {
62+
let iso = #isolation
63+
print("Task{} #isolation = \(String(describing: iso))")
64+
}.value
65+
66+
await Task {
67+
let iso = #isolation
68+
print("Task{ [outerIsolation] } outerIsolation = \(String(describing: outerIsolation)), #iso = \(String(describing: iso))")
69+
}.value
70+
71+
print("done - \(#function)")
72+
}

0 commit comments

Comments
 (0)