@@ -6494,18 +6494,31 @@ ArgumentList *ExprRewriter::coerceCallArguments(
64946494 return ArgumentList::createTypeChecked (ctx, args, newArgs);
64956495}
64966496
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) {
65006500 if (auto IE = dyn_cast<IdentityExpr>(expr))
6501- return closureInheritsActorContext (IE->getSubExpr ());
6501+ return isExplicitClosureExpr (IE->getSubExpr ());
65026502
65036503 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+ }
65056508
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))
65076513 return CE->inheritsActorContext ();
6514+ return false ;
6515+ }
65086516
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>();
65096522 return false ;
65106523}
65116524
@@ -7747,6 +7760,23 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
77477760 }
77487761 }
77497762
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+
77507780 if (ctx.LangOpts .isDynamicActorIsolationCheckingEnabled ()) {
77517781 // Passing a synchronous global actor-isolated function value and
77527782 // parameter that expects a synchronous non-isolated function type could
0 commit comments