@@ -5710,17 +5710,25 @@ static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
5710
5710
5711
5711
// / Apply the contextually Sendable flag to the given expression,
5712
5712
static void applyContextualClosureFlags (
5713
- Expr *expr, bool sendable, bool forMainActor, bool implicitSelfCapture) {
5713
+ Expr *expr, bool sendable, bool forMainActor, bool implicitSelfCapture,
5714
+ bool inheritActorContext) {
5714
5715
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
5715
5716
closure->setUnsafeConcurrent (sendable, forMainActor);
5716
5717
closure->setAllowsImplicitSelfCapture (implicitSelfCapture);
5718
+ closure->setInheritsActorContext (inheritActorContext);
5717
5719
return ;
5718
5720
}
5719
5721
5720
5722
if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
5721
5723
applyContextualClosureFlags (
5722
5724
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);
5724
5732
}
5725
5733
}
5726
5734
@@ -5958,9 +5966,10 @@ Expr *ExprRewriter::coerceCallArguments(
5958
5966
bool isMainActor = paramInfo.isUnsafeMainActor (paramIdx) ||
5959
5967
(isUnsafeSendable && apply && isMainDispatchQueue (apply->getFn ()));
5960
5968
bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture (paramIdx);
5969
+ bool inheritsActorContext = paramInfo.inheritsActorContext (paramIdx);
5961
5970
applyContextualClosureFlags (
5962
5971
arg, isUnsafeSendable && contextUsesConcurrencyFeatures (dc),
5963
- isMainActor, isImplicitSelfCapture);
5972
+ isMainActor, isImplicitSelfCapture, inheritsActorContext );
5964
5973
5965
5974
// If the types exactly match, this is easy.
5966
5975
auto paramType = param.getOldType ();
@@ -6113,6 +6122,20 @@ static bool isClosureLiteralExpr(Expr *expr) {
6113
6122
return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
6114
6123
}
6115
6124
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
+
6116
6139
// / If the expression is an explicit closure expression (potentially wrapped in
6117
6140
// / IdentityExprs), change the type of the closure and identities to the
6118
6141
// / specified type and return true. Otherwise, return false with no effect.
@@ -6976,8 +6999,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6976
6999
}
6977
7000
}
6978
7001
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.
6981
7004
auto fromEI = fromFunc->getExtInfo ();
6982
7005
if (toEI.isSendable () && !fromEI.isSendable ()) {
6983
7006
auto newFromFuncType = fromFunc->withExtInfo (fromEI.withConcurrent ());
@@ -6991,6 +7014,22 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6991
7014
}
6992
7015
}
6993
7016
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
+
6994
7033
// If we have a ClosureExpr, then we can safely propagate a global actor
6995
7034
// to the closure without invalidating prior analysis.
6996
7035
fromEI = fromFunc->getExtInfo ();
0 commit comments