Skip to content

Commit a8d46aa

Browse files
committed
[Concurrency] Calls that pass an isolated parameter matching the isolation of
the context do not exit to nonisolated. Setting the `mayExitToNonisolated` during isolated parameter checking was done after a check that bails out early when the isolated argument matches the isolated paramter of the caller, so the actor isolation checker was accidentally considering the call as exiting to a nonisolated context. This lead to bogus diagnostics during the region isolation pass. (cherry picked from commit 2804daf)
1 parent c4cddb4 commit a8d46aa

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3457,6 +3457,15 @@ namespace {
34573457

34583458
argForIsolatedParam = arg;
34593459
unsatisfiedIsolation = std::nullopt;
3460+
3461+
// Assume that a callee with an isolated parameter does not
3462+
// cross an isolation boundary. We'll set this again below if
3463+
// the given isolated argument doesn't match the isolation of the
3464+
// caller.
3465+
mayExitToNonisolated = false;
3466+
3467+
// If the argument is an isolated parameter from the enclosing context,
3468+
// or #isolation, then the call does not cross an isolation boundary.
34603469
if (getIsolatedActor(arg) || isa<CurrentContextIsolationExpr>(arg))
34613470
continue;
34623471

@@ -3471,7 +3480,6 @@ namespace {
34713480
KnownProtocolKind::Actor);
34723481
}
34733482

3474-
mayExitToNonisolated = false;
34753483
auto calleeIsolation = ActorIsolation::forActorInstanceParameter(
34763484
const_cast<Expr *>(arg->findOriginalValue()), paramIdx);
34773485

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 %s -emit-sil -o /dev/null -verify
2+
3+
public func doNotCross(
4+
isolation: isolated (any Actor)? = #isolation,
5+
_ block: () async -> Void
6+
) async {
7+
await block()
8+
}
9+
10+
actor MyActor {
11+
func doStuff() {}
12+
13+
func test() async {
14+
await doNotCross {
15+
doStuff()
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)