@@ -5710,17 +5710,25 @@ static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
57105710
57115711// / Apply the contextually Sendable flag to the given expression,
57125712static void applyContextualClosureFlags (
5713- Expr *expr, bool sendable, bool forMainActor, bool implicitSelfCapture) {
5713+ Expr *expr, bool sendable, bool forMainActor, bool implicitSelfCapture,
5714+ bool inheritActorContext) {
57145715 if (auto closure = dyn_cast<ClosureExpr>(expr)) {
57155716 closure->setUnsafeConcurrent (sendable, forMainActor);
57165717 closure->setAllowsImplicitSelfCapture (implicitSelfCapture);
5718+ closure->setInheritsActorContext (inheritActorContext);
57175719 return ;
57185720 }
57195721
57205722 if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
57215723 applyContextualClosureFlags (
57225724 captureList->getClosureBody (), sendable, forMainActor,
5723- implicitSelfCapture);
5725+ implicitSelfCapture, inheritActorContext);
5726+ }
5727+
5728+ if (auto identity = dyn_cast<IdentityExpr>(expr)) {
5729+ applyContextualClosureFlags (
5730+ identity->getSubExpr (), sendable, forMainActor,
5731+ implicitSelfCapture, inheritActorContext);
57245732 }
57255733}
57265734
@@ -5958,9 +5966,10 @@ Expr *ExprRewriter::coerceCallArguments(
59585966 bool isMainActor = paramInfo.isUnsafeMainActor (paramIdx) ||
59595967 (isUnsafeSendable && apply && isMainDispatchQueue (apply->getFn ()));
59605968 bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture (paramIdx);
5969+ bool inheritsActorContext = paramInfo.inheritsActorContext (paramIdx);
59615970 applyContextualClosureFlags (
59625971 arg, isUnsafeSendable && contextUsesConcurrencyFeatures (dc),
5963- isMainActor, isImplicitSelfCapture);
5972+ isMainActor, isImplicitSelfCapture, inheritsActorContext );
59645973
59655974 // If the types exactly match, this is easy.
59665975 auto paramType = param.getOldType ();
@@ -6113,6 +6122,20 @@ static bool isClosureLiteralExpr(Expr *expr) {
61136122 return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
61146123}
61156124
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+
61166139// / If the expression is an explicit closure expression (potentially wrapped in
61176140// / IdentityExprs), change the type of the closure and identities to the
61186141// / specified type and return true. Otherwise, return false with no effect.
@@ -6976,8 +6999,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69766999 }
69777000 }
69787001
6979- // If we have a ClosureExpr, then we can safely propagate the 'concurrent'
6980- // bit to the closure without invalidating prior analysis.
7002+ // If we have a ClosureExpr, then we can safely propagate @Sendable
7003+ // to the closure without invalidating prior analysis.
69817004 auto fromEI = fromFunc->getExtInfo ();
69827005 if (toEI.isSendable () && !fromEI.isSendable ()) {
69837006 auto newFromFuncType = fromFunc->withExtInfo (fromEI.withConcurrent ());
@@ -6991,6 +7014,22 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69917014 }
69927015 }
69937016
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+
69947033 // If we have a ClosureExpr, then we can safely propagate a global actor
69957034 // to the closure without invalidating prior analysis.
69967035 fromEI = fromFunc->getExtInfo ();
0 commit comments