Skip to content

Commit d1f66c0

Browse files
authored
Merge pull request swiftlang#76326 from hborla/isolated-operator-crash
[Concurrency] Handle implicitly async operator expressions in the actor isolation checker.
2 parents e34d23f + 0312054 commit d1f66c0

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,22 +2887,27 @@ namespace {
28872887
assert(applyStack.size() > 0 && "not contained within an Apply?");
28882888

28892889
const auto End = applyStack.rend();
2890-
for (auto I = applyStack.rbegin(); I != End; ++I)
2891-
if (auto call = dyn_cast<CallExpr>(I->dyn_cast<ApplyExpr *>())) {
2892-
if (setAsync) {
2893-
call->setImplicitlyAsync(*setAsync);
2894-
}
2895-
if (setThrows) {
2896-
call->setImplicitlyThrows(true);
2897-
}else {
2898-
call->setImplicitlyThrows(false);
2899-
}
2900-
if (setDistributedThunk) {
2901-
call->setShouldApplyDistributedThunk(true);
2902-
}
2903-
return;
2890+
for (auto I = applyStack.rbegin(); I != End; ++I) {
2891+
auto *apply = I->dyn_cast<ApplyExpr *>();
2892+
if (!apply || isa<SelfApplyExpr>(apply)) {
2893+
continue;
2894+
}
2895+
2896+
if (setAsync) {
2897+
apply->setImplicitlyAsync(*setAsync);
29042898
}
2905-
llvm_unreachable("expected a CallExpr in applyStack!");
2899+
if (setThrows) {
2900+
apply->setImplicitlyThrows(true);
2901+
} else {
2902+
apply->setImplicitlyThrows(false);
2903+
}
2904+
if (setDistributedThunk) {
2905+
apply->setShouldApplyDistributedThunk(true);
2906+
}
2907+
return;
2908+
}
2909+
2910+
llvm_unreachable("expected an ApplyExpr in applyStack!");
29062911
}
29072912

29082913
MacroWalking getMacroWalkingBehavior() const override {

test/Concurrency/actor_call_implicitly_async.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,3 +576,23 @@ func tryTheActorSubscripts(a : SubscriptA, t : SubscriptT, at : SubscriptAT) asy
576576

577577
_ = try await at[0]
578578
}
579+
580+
@MainActor
581+
final class IsolatedOperator: @preconcurrency Equatable {
582+
static func == (lhs: IsolatedOperator, rhs: IsolatedOperator) -> Bool {
583+
lhs.num == rhs.num
584+
}
585+
586+
var num = 0
587+
588+
init(num: Int = 0) {
589+
self.num = num
590+
}
591+
592+
nonisolated func callEqual() async -> Bool {
593+
let foo = await IsolatedOperator()
594+
// expected-error@+2{{expression is 'async' but is not marked with 'await'}}
595+
// expected-note@+1{{calls to operator function '==' from outside of its actor context are implicitly asynchronous}}
596+
return foo == self
597+
}
598+
}

0 commit comments

Comments
 (0)