Skip to content

Commit 6928c3f

Browse files
committed
Make sure that we perform the actor hop for @_inheritActorContext
1 parent b9f1e7f commit 6928c3f

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

lib/Sema/CSApply.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5724,6 +5724,12 @@ static void applyContextualClosureFlags(
57245724
captureList->getClosureBody(), sendable, forMainActor,
57255725
implicitSelfCapture, inheritActorContext);
57265726
}
5727+
5728+
if (auto identity = dyn_cast<IdentityExpr>(expr)) {
5729+
applyContextualClosureFlags(
5730+
identity->getSubExpr(), sendable, forMainActor,
5731+
implicitSelfCapture, inheritActorContext);
5732+
}
57275733
}
57285734

57295735
/// Whether this is a reference to a method on the main dispatch queue.
@@ -6116,6 +6122,20 @@ static bool isClosureLiteralExpr(Expr *expr) {
61166122
return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
61176123
}
61186124

6125+
/// Whether we should propagate async down to a closure.
6126+
static bool shouldPropagateAsyncToClosure(Expr *expr) {
6127+
if (auto IE = dyn_cast<IdentityExpr>(expr))
6128+
return shouldPropagateAsyncToClosure(IE->getSubExpr());
6129+
6130+
if (auto CLE = dyn_cast<CaptureListExpr>(expr))
6131+
return shouldPropagateAsyncToClosure(CLE->getClosureBody());
6132+
6133+
if (auto CE = dyn_cast<ClosureExpr>(expr))
6134+
return CE->inheritsActorContext();
6135+
6136+
return false;
6137+
}
6138+
61196139
/// If the expression is an explicit closure expression (potentially wrapped in
61206140
/// IdentityExprs), change the type of the closure and identities to the
61216141
/// specified type and return true. Otherwise, return false with no effect.
@@ -6994,6 +7014,22 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69947014
}
69957015
}
69967016

7017+
// If we have a ClosureExpr, then we can safely propagate the 'async'
7018+
// bit to the closure without invalidating prior analysis.
7019+
fromEI = fromFunc->getExtInfo();
7020+
if (toEI.isAsync() && !fromEI.isAsync() &&
7021+
shouldPropagateAsyncToClosure(expr)) {
7022+
auto newFromFuncType = fromFunc->withExtInfo(fromEI.withAsync());
7023+
if (applyTypeToClosureExpr(cs, expr, newFromFuncType)) {
7024+
fromFunc = newFromFuncType->castTo<FunctionType>();
7025+
7026+
// Propagating the 'concurrent' bit might have satisfied the entire
7027+
// conversion. If so, we're done, otherwise keep converting.
7028+
if (fromFunc->isEqual(toType))
7029+
return expr;
7030+
}
7031+
}
7032+
69977033
// If we have a ClosureExpr, then we can safely propagate a global actor
69987034
// to the closure without invalidating prior analysis.
69997035
fromEI = fromFunc->getExtInfo();

test/Concurrency/actor_isolation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ func testCrossActorProtocol<T: P>(t: T) async {
756756
}
757757

758758
// ----------------------------------------------------------------------
759-
// @_
759+
// @_inheritActorContext
760760
// ----------------------------------------------------------------------
761761
func acceptAsyncSendableClosure<T>(_: @Sendable () async -> T) { }
762762
func acceptAsyncSendableClosureInheriting<T>(@_inheritActorContext _: @Sendable () async -> T) { }

test/SILGen/hop_to_executor.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,20 @@ func anotherUnspecifiedAsyncFunc(_ red : RedActorImpl) async {
245245
func testGlobalActorFuncValue(_ fn: @RedActor () -> Void) async {
246246
await fn()
247247
}
248+
249+
func acceptAsyncSendableClosureInheriting<T>(@_inheritActorContext _: @Sendable () async -> T) { }
250+
251+
extension MyActor {
252+
func synchronous() { }
253+
254+
// CHECK-LABEL: sil private [ossa] @$s4test7MyActorC0A10InheritingyyFyyYaYbXEfU_
255+
// CHECK: debug_value [[SELF:%[0-9]+]] : $MyActor
256+
// CHECK-NEXT: [[COPY:%[0-9]+]] = copy_value [[SELF]] : $MyActor
257+
// CHECK-NEXT: [[BORROW:%[0-9]+]] = begin_borrow [[COPY]] : $MyActor
258+
// CHECK-NEXT: hop_to_executor [[BORROW]] : $MyActor
259+
func testInheriting() {
260+
acceptAsyncSendableClosureInheriting {
261+
synchronous()
262+
}
263+
}
264+
}

0 commit comments

Comments
 (0)