@@ -6514,18 +6514,31 @@ ArgumentList *ExprRewriter::coerceCallArguments(
6514
6514
return ArgumentList::createTypeChecked (ctx, args, newArgs);
6515
6515
}
6516
6516
6517
- // / Whether the given expression is a closure that should inherit
6518
- // / the actor context from where it was formed .
6519
- static bool closureInheritsActorContext (Expr *expr) {
6517
+ // / Looks through any non-semantic expressions and a capture list
6518
+ // / to find out whether the given expression is an explicit closure .
6519
+ static ClosureExpr * isExplicitClosureExpr (Expr *expr) {
6520
6520
if (auto IE = dyn_cast<IdentityExpr>(expr))
6521
- return closureInheritsActorContext (IE->getSubExpr ());
6521
+ return isExplicitClosureExpr (IE->getSubExpr ());
6522
6522
6523
6523
if (auto CLE = dyn_cast<CaptureListExpr>(expr))
6524
- return closureInheritsActorContext (CLE->getClosureBody ());
6524
+ return isExplicitClosureExpr (CLE->getClosureBody ());
6525
+
6526
+ return dyn_cast<ClosureExpr>(expr);
6527
+ }
6525
6528
6526
- if (auto CE = dyn_cast<ClosureExpr>(expr))
6529
+ // / Whether the given expression is a closure that should inherit
6530
+ // / the actor context from where it was formed.
6531
+ static bool closureInheritsActorContext (Expr *expr) {
6532
+ if (auto *CE = isExplicitClosureExpr (expr))
6527
6533
return CE->inheritsActorContext ();
6534
+ return false ;
6535
+ }
6528
6536
6537
+ // / Determine whether the given expression is a closure that
6538
+ // / is explicitly marked as `@concurrent`.
6539
+ static bool isClosureMarkedAsConcurrent (Expr *expr) {
6540
+ if (auto *CE = isExplicitClosureExpr (expr))
6541
+ return CE->getAttrs ().hasAttribute <ConcurrentAttr>();
6529
6542
return false ;
6530
6543
}
6531
6544
@@ -7767,6 +7780,23 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
7767
7780
}
7768
7781
}
7769
7782
7783
+ // If we have a ClosureExpr, then we can safely propagate the
7784
+ // 'nonisolated(nonsending)' isolation if it's not explicitly
7785
+ // marked as `@concurrent`.
7786
+ if (toEI.getIsolation ().isNonIsolatedCaller () &&
7787
+ (fromEI.getIsolation ().isNonIsolated () &&
7788
+ !isClosureMarkedAsConcurrent (expr))) {
7789
+ auto newFromFuncType = fromFunc->withIsolation (
7790
+ FunctionTypeIsolation::forNonIsolatedCaller ());
7791
+ if (applyTypeToClosureExpr (cs, expr, newFromFuncType)) {
7792
+ fromFunc = newFromFuncType->castTo <FunctionType>();
7793
+ // Propagating 'nonisolated(nonsending)' might have satisfied the entire
7794
+ // conversion. If so, we're done, otherwise keep converting.
7795
+ if (fromFunc->isEqual (toType))
7796
+ return expr;
7797
+ }
7798
+ }
7799
+
7770
7800
if (ctx.LangOpts .isDynamicActorIsolationCheckingEnabled ()) {
7771
7801
// Passing a synchronous global actor-isolated function value and
7772
7802
// parameter that expects a synchronous non-isolated function type could
0 commit comments