|
25 | 25 | #include "swift/AST/ASTVisitor.h"
|
26 | 26 | #include "swift/AST/ASTWalker.h"
|
27 | 27 | #include "swift/AST/ClangModuleLoader.h"
|
| 28 | +#include "swift/AST/Effects.h" |
28 | 29 | #include "swift/AST/ExistentialLayout.h"
|
29 | 30 | #include "swift/AST/GenericEnvironment.h"
|
30 | 31 | #include "swift/AST/GenericSignature.h"
|
@@ -7043,6 +7044,38 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
7043 | 7044 | }
|
7044 | 7045 | }
|
7045 | 7046 |
|
| 7047 | + /// Whether the given effect should be propagated to a closure expression. |
| 7048 | + auto shouldApplyEffect = [&](EffectKind kind) -> bool { |
| 7049 | + auto last = locator.last(); |
| 7050 | + if (!(last && last->is<LocatorPathElt::ApplyArgToParam>())) |
| 7051 | + return true; |
| 7052 | + |
| 7053 | + // The effect should not be applied if the closure is an argument |
| 7054 | + // to a function where that effect is polymorphic. |
| 7055 | + if (auto *call = getAsExpr<ApplyExpr>(locator.getAnchor())) { |
| 7056 | + if (auto *declRef = dyn_cast<DeclRefExpr>(call->getFn())) { |
| 7057 | + if (auto *fn = dyn_cast<AbstractFunctionDecl>(declRef->getDecl())) |
| 7058 | + return !fn->hasPolymorphicEffect(kind); |
| 7059 | + } |
| 7060 | + } |
| 7061 | + |
| 7062 | + return true; |
| 7063 | + }; |
| 7064 | + |
| 7065 | + // If we have a ClosureExpr, we can safely propagate 'async' to the closure. |
| 7066 | + fromEI = fromFunc->getExtInfo(); |
| 7067 | + if (toEI.isAsync() && !fromEI.isAsync() && shouldApplyEffect(EffectKind::Async)) { |
| 7068 | + auto newFromFuncType = fromFunc->withExtInfo(fromEI.withAsync()); |
| 7069 | + if (applyTypeToClosureExpr(cs, expr, newFromFuncType)) { |
| 7070 | + fromFunc = newFromFuncType->castTo<FunctionType>(); |
| 7071 | + |
| 7072 | + // Propagating 'async' might have satisfied the entire conversion. |
| 7073 | + // If so, we're done, otherwise keep converting. |
| 7074 | + if (fromFunc->isEqual(toType)) |
| 7075 | + return expr; |
| 7076 | + } |
| 7077 | + } |
| 7078 | + |
7046 | 7079 | // If we have a ClosureExpr, then we can safely propagate the 'no escape'
|
7047 | 7080 | // bit to the closure without invalidating prior analysis.
|
7048 | 7081 | fromEI = fromFunc->getExtInfo();
|
|
0 commit comments