@@ -6494,18 +6494,31 @@ ArgumentList *ExprRewriter::coerceCallArguments(
6494
6494
return ArgumentList::createTypeChecked (ctx, args, newArgs);
6495
6495
}
6496
6496
6497
- // / Whether the given expression is a closure that should inherit
6498
- // / the actor context from where it was formed .
6499
- static bool closureInheritsActorContext (Expr *expr) {
6497
+ // / Looks through any non-semantic expressions and a capture list
6498
+ // / to find out whether the given expression is an explicit closure .
6499
+ static ClosureExpr * isExplicitClosureExpr (Expr *expr) {
6500
6500
if (auto IE = dyn_cast<IdentityExpr>(expr))
6501
- return closureInheritsActorContext (IE->getSubExpr ());
6501
+ return isExplicitClosureExpr (IE->getSubExpr ());
6502
6502
6503
6503
if (auto CLE = dyn_cast<CaptureListExpr>(expr))
6504
- return closureInheritsActorContext (CLE->getClosureBody ());
6504
+ return isExplicitClosureExpr (CLE->getClosureBody ());
6505
+
6506
+ return dyn_cast<ClosureExpr>(expr);
6507
+ }
6505
6508
6506
- if (auto CE = dyn_cast<ClosureExpr>(expr))
6509
+ // / Whether the given expression is a closure that should inherit
6510
+ // / the actor context from where it was formed.
6511
+ static bool closureInheritsActorContext (Expr *expr) {
6512
+ if (auto *CE = isExplicitClosureExpr (expr))
6507
6513
return CE->inheritsActorContext ();
6514
+ return false ;
6515
+ }
6508
6516
6517
+ // / Determine whether the given expression is a closure that
6518
+ // / is explicitly marked as `@concurrent`.
6519
+ static bool isClosureMarkedAsConcurrent (Expr *expr) {
6520
+ if (auto *CE = isExplicitClosureExpr (expr))
6521
+ return CE->getAttrs ().hasAttribute <ConcurrentAttr>();
6509
6522
return false ;
6510
6523
}
6511
6524
@@ -7747,6 +7760,23 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
7747
7760
}
7748
7761
}
7749
7762
7763
+ // If we have a ClosureExpr, then we can safely propagate the
7764
+ // 'nonisolated(nonsending)' isolation if it's not explicitly
7765
+ // marked as `@concurrent`.
7766
+ if (toEI.getIsolation ().isNonIsolatedCaller () &&
7767
+ (fromEI.getIsolation ().isNonIsolated () &&
7768
+ !isClosureMarkedAsConcurrent (expr))) {
7769
+ auto newFromFuncType = fromFunc->withIsolation (
7770
+ FunctionTypeIsolation::forNonIsolatedCaller ());
7771
+ if (applyTypeToClosureExpr (cs, expr, newFromFuncType)) {
7772
+ fromFunc = newFromFuncType->castTo <FunctionType>();
7773
+ // Propagating 'nonisolated(nonsending)' might have satisfied the entire
7774
+ // conversion. If so, we're done, otherwise keep converting.
7775
+ if (fromFunc->isEqual (toType))
7776
+ return expr;
7777
+ }
7778
+ }
7779
+
7750
7780
if (ctx.LangOpts .isDynamicActorIsolationCheckingEnabled ()) {
7751
7781
// Passing a synchronous global actor-isolated function value and
7752
7782
// parameter that expects a synchronous non-isolated function type could
0 commit comments