Skip to content

Commit

Permalink
[Concurrency] Calls that pass an isolated parameter matching the isol…
Browse files Browse the repository at this point in the history
…ation 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.
  • Loading branch information
hborla committed Jun 19, 2024
1 parent 4bec599 commit 2804daf
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
10 changes: 9 additions & 1 deletion lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3463,6 +3463,15 @@ namespace {

argForIsolatedParam = arg;
unsatisfiedIsolation = std::nullopt;

// Assume that a callee with an isolated parameter does not
// cross an isolation boundary. We'll set this again below if
// the given isolated argument doesn't match the isolation of the
// caller.
mayExitToNonisolated = false;

// If the argument is an isolated parameter from the enclosing context,
// or #isolation, then the call does not cross an isolation boundary.
if (getIsolatedActor(arg) || isa<CurrentContextIsolationExpr>(arg))
continue;

Expand All @@ -3477,7 +3486,6 @@ namespace {
KnownProtocolKind::Actor);
}

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

Expand Down
18 changes: 18 additions & 0 deletions test/Concurrency/isolated_parameter_valid.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 %s -emit-sil -o /dev/null -verify

public func doNotCross(
isolation: isolated (any Actor)? = #isolation,
_ block: () async -> Void
) async {
await block()
}

actor MyActor {
func doStuff() {}

func test() async {
await doNotCross {
doStuff()
}
}
}

0 comments on commit 2804daf

Please sign in to comment.