Skip to content

Commit c6f223f

Browse files
authored
Merge pull request #82793 from ktoso/wip-correct-isolated-handling-with-caller-isolation
2 parents f7ccb52 + b1ca06d commit c6f223f

File tree

4 files changed

+125
-8
lines changed

4 files changed

+125
-8
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7295,19 +7295,34 @@ 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+
auto ctor = dyn_cast_or_null<ConstructorDecl>(afd);
7303+
if (ctor && ctor->isDesignatedInit() &&
73057304
isolation == ActorIsolation::ActorInstance &&
73067305
isolation.getActorInstance() == ctor->getImplicitSelfDecl()) {
7306+
// If we are in an actor initializer that is isolated to self, the
7307+
// current isolation is flow-sensitive; use that instead of the
7308+
// synthesized expression.
73077309
auto isolationValue =
73087310
SGF.emitFlowSensitiveSelfIsolation(E, isolation);
73097311
return RValue(SGF, E, isolationValue);
73107312
}
7313+
7314+
if (isolation == ActorIsolation::CallerIsolationInheriting) {
7315+
auto *isolatedArg = SGF.F.maybeGetIsolatedArgument();
7316+
assert(isolatedArg &&
7317+
"Caller Isolation Inheriting without isolated parameter");
7318+
ManagedValue isolatedMV;
7319+
if (isolatedArg->getOwnershipKind() == OwnershipKind::Guaranteed) {
7320+
isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
7321+
} else {
7322+
isolatedMV = ManagedValue::forUnmanagedOwnedValue(isolatedArg);
7323+
}
7324+
return RValue(SGF, E, isolatedMV);
7325+
}
73117326
}
73127327

73137328
return visit(E->getActor(), C);

lib/Sema/TypeCheckConcurrency.cpp

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

43924392
case ActorIsolation::Unspecified:
43934393
case ActorIsolation::Nonisolated:
4394-
case ActorIsolation::CallerIsolationInheriting:
43954394
case ActorIsolation::NonisolatedUnsafe:
43964395
actorExpr = new (ctx) NilLiteralExpr(loc, /*implicit=*/false);
43974396
break;
4397+
case ActorIsolation::CallerIsolationInheriting:
4398+
// For caller isolation this expression will be replaced in SILGen
4399+
// because we're adding an implicit isolated parameter that #isolated
4400+
// must resolve to, but cannot do so during AST expansion quite yet.
4401+
actorExpr = new (ctx) NilLiteralExpr(loc, /*implicit=*/false);
4402+
break;
43984403
}
43994404

44004405

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+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-frontend -parse-as-library -emit-sil %s | %FileCheck %s
2+
3+
// REQUIRES: concurrency
4+
5+
nonisolated(nonsending) func nonisolatedNonsending() async {
6+
let iso = #isolation
7+
take(iso: iso)
8+
}
9+
10+
func take(iso: (any Actor)?) {}
11+
12+
// CHECK-LABEL: // nonisolatedNonsending()
13+
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
14+
// CHECK-NEXT: sil hidden @$s39isolated_nonsending_isolation_macro_sil21nonisolatedNonsendingyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
15+
// CHECK: bb0(%0 : $Optional<any Actor>):
16+
// CHECK-NEXT: hop_to_executor %0 // id: %1
17+
// CHECK-NEXT: retain_value %0 // id: %2
18+
// CHECK-NEXT: debug_value %0, let, name "iso" // id: %3
19+
// CHECK-NEXT: // function_ref take(iso:)
20+
// CHECK-NEXT: %4 = function_ref @$s39isolated_nonsending_isolation_macro_sil4take3isoyScA_pSg_tF : $@convention(thin) (@guaranteed Optional<any Actor>) -> () // user: %5
21+
// CHECK-NEXT: %5 = apply %4(%0) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
22+
// CHECK-NEXT: release_value %0 // id: %6
23+
// CHECK-NEXT: %7 = tuple () // user: %8
24+
// CHECK-NEXT: return %7 // id: %8
25+
// CHECK-NEXT: } // end sil function '$s39isolated_nonsending_isolation_macro_sil21nonisolatedNonsendingyyYaF'

0 commit comments

Comments
 (0)