|
29 | 29 | #include "swift/AST/NameLookupRequests.h"
|
30 | 30 | #include "swift/AST/ParameterList.h"
|
31 | 31 | #include "swift/AST/PropertyWrappers.h"
|
| 32 | +#include "swift/AST/ProtocolConformance.h" |
32 | 33 | #include "swift/AST/SourceFile.h"
|
33 | 34 | #include "swift/AST/StorageImpl.h"
|
34 | 35 | #include "swift/AST/TypeCheckRequests.h"
|
@@ -5248,5 +5249,58 @@ bool IsAsyncHandlerRequest::evaluate(
|
5248 | 5249 | return true;
|
5249 | 5250 | }
|
5250 | 5251 |
|
| 5252 | + // Are we in a context where inference is possible? |
| 5253 | + auto dc = func->getDeclContext(); |
| 5254 | + if (!dc->isTypeContext() || !dc->getParentSourceFile() || |
| 5255 | + isa<ProtocolDecl>(dc) || !func->hasBody()) |
| 5256 | + return false; |
| 5257 | + |
| 5258 | + // Is it possible to infer @asyncHandler for this function at all? |
| 5259 | + if (checkAsyncHandler(func, /*diagnose=*/false)) |
| 5260 | + return false; |
| 5261 | + |
| 5262 | + // Add an implicit @asyncHandler attribute and return true. We're done. |
| 5263 | + auto addImplicitAsyncHandlerAttr = [&] { |
| 5264 | + func->getAttrs().add(new (func->getASTContext()) AsyncHandlerAttr(true)); |
| 5265 | + return true; |
| 5266 | + }; |
| 5267 | + |
| 5268 | + // Check whether any of the conformances in the context of the function |
| 5269 | + // implies @asyncHandler. |
| 5270 | + { |
| 5271 | + auto idc = cast<IterableDeclContext>(dc->getAsDecl()); |
| 5272 | + auto conformances = evaluateOrDefault( |
| 5273 | + dc->getASTContext().evaluator, |
| 5274 | + LookupAllConformancesInContextRequest{idc}, { }); |
| 5275 | + |
| 5276 | + for (auto conformance : conformances) { |
| 5277 | + auto protocol = conformance->getProtocol(); |
| 5278 | + for (auto found : protocol->lookupDirect(func->getName())) { |
| 5279 | + if (!isa<ProtocolDecl>(found->getDeclContext())) |
| 5280 | + continue; |
| 5281 | + |
| 5282 | + auto requirement = dyn_cast<FuncDecl>(found); |
| 5283 | + if (!requirement) |
| 5284 | + continue; |
| 5285 | + |
| 5286 | + if (!requirement->isAsyncHandler()) |
| 5287 | + continue; |
| 5288 | + |
| 5289 | + auto witness = conformance->getWitnessDecl(requirement); |
| 5290 | + if (witness != func) |
| 5291 | + continue; |
| 5292 | + |
| 5293 | + return addImplicitAsyncHandlerAttr(); |
| 5294 | + } |
| 5295 | + } |
| 5296 | + } |
| 5297 | + |
| 5298 | + // Look through dynamic replacements. |
| 5299 | + if (auto replaced = func->getDynamicallyReplacedDecl()) { |
| 5300 | + if (auto replacedFunc = dyn_cast<FuncDecl>(replaced)) |
| 5301 | + if (replacedFunc->isAsyncHandler()) |
| 5302 | + return addImplicitAsyncHandlerAttr(); |
| 5303 | + } |
| 5304 | + |
5251 | 5305 | return false;
|
5252 | 5306 | }
|
0 commit comments