|
15 | 15 | //===----------------------------------------------------------------------===//
|
16 | 16 | #include "swift/AST/ParseRequests.h"
|
17 | 17 | #include "swift/AST/ASTContext.h"
|
| 18 | +#include "swift/AST/ASTWalker.h" |
18 | 19 | #include "swift/AST/AvailabilitySpec.h"
|
19 | 20 | #include "swift/AST/Decl.h"
|
20 | 21 | #include "swift/AST/DeclContext.h"
|
21 | 22 | #include "swift/AST/Module.h"
|
22 | 23 | #include "swift/AST/SourceFile.h"
|
| 24 | +#include "swift/AST/TypeRepr.h" |
23 | 25 | #include "swift/Basic/Assertions.h"
|
24 | 26 | #include "swift/Basic/Defer.h"
|
25 | 27 | #include "swift/Bridging/ASTGen.h"
|
@@ -47,6 +49,82 @@ void swift::simple_display(llvm::raw_ostream &out,
|
47 | 49 | simple_display(out, value.members);
|
48 | 50 | }
|
49 | 51 |
|
| 52 | +namespace { |
| 53 | + |
| 54 | +/// Find 'ValueDecl' with opaque type results and let \p SF track the opaque |
| 55 | +/// return type mapping. |
| 56 | +// FIXME: This should be done in Sema or AST? |
| 57 | +class OpaqueResultCollector : public ASTWalker { |
| 58 | + SourceFile &SF; |
| 59 | + |
| 60 | +public: |
| 61 | + OpaqueResultCollector(SourceFile &SF) : SF(SF) {} |
| 62 | + |
| 63 | + void handle(ValueDecl *VD) const { |
| 64 | + TypeRepr *tyR = nullptr; |
| 65 | + if (auto *FD = dyn_cast<FuncDecl>(VD)) { |
| 66 | + if (isa<AccessorDecl>(VD)) |
| 67 | + return; |
| 68 | + tyR = FD->getResultTypeRepr(); |
| 69 | + } else if (auto *VarD = dyn_cast<VarDecl>(VD)) { |
| 70 | + if (!VarD->getParentPatternBinding()) |
| 71 | + return; |
| 72 | + tyR = VarD->getTypeReprOrParentPatternTypeRepr(); |
| 73 | + } else if (auto *SD = dyn_cast<SubscriptDecl>(VD)) { |
| 74 | + tyR = SD->getElementTypeRepr(); |
| 75 | + } |
| 76 | + |
| 77 | + if (!tyR || !tyR->hasOpaque()) |
| 78 | + return; |
| 79 | + |
| 80 | + SF.addUnvalidatedDeclWithOpaqueResultType(VD); |
| 81 | + } |
| 82 | + |
| 83 | + PreWalkAction walkToDeclPre(Decl *D) override { |
| 84 | + if (auto *VD = dyn_cast<ValueDecl>(D)) |
| 85 | + handle(VD); |
| 86 | + |
| 87 | + if (auto *IDC = dyn_cast<IterableDeclContext>(D)) { |
| 88 | + // Only walk into cached parsed members to avoid invoking lazy parsing. |
| 89 | + ParseMembersRequest req(IDC); |
| 90 | + if (SF.getASTContext().evaluator.hasCachedResult(req)) { |
| 91 | + auto memberResult = evaluateOrFatal(SF.getASTContext().evaluator, req); |
| 92 | + for (auto *D : memberResult.members) |
| 93 | + D->walk(*this); |
| 94 | + } |
| 95 | + return Action::SkipChildren(); |
| 96 | + } |
| 97 | + |
| 98 | + return Action::Continue(); |
| 99 | + } |
| 100 | + |
| 101 | + MacroWalking getMacroWalkingBehavior() const override { |
| 102 | + return MacroWalking::None; |
| 103 | + } |
| 104 | + |
| 105 | + PreWalkAction walkToTypeReprPre(TypeRepr *T) override { |
| 106 | + return Action::SkipNode(); |
| 107 | + } |
| 108 | +}; |
| 109 | + |
| 110 | +void registerDeclWithOpaqueResultType(SourceFile *SF, ArrayRef<ASTNode> items) { |
| 111 | + if (!SF) |
| 112 | + return; |
| 113 | + OpaqueResultCollector walker(*SF); |
| 114 | + for (const ASTNode &item : items) |
| 115 | + const_cast<ASTNode &>(item).walk(walker); |
| 116 | +} |
| 117 | + |
| 118 | +void registerDeclWithOpaqueResultType(SourceFile *SF, ArrayRef<Decl *> items) { |
| 119 | + if (!SF) |
| 120 | + return; |
| 121 | + OpaqueResultCollector walker(*SF); |
| 122 | + for (Decl *item : items) |
| 123 | + item->walk(walker); |
| 124 | +} |
| 125 | + |
| 126 | +} // namespace |
| 127 | + |
50 | 128 | FingerprintAndMembers
|
51 | 129 | ParseMembersRequest::evaluate(Evaluator &evaluator,
|
52 | 130 | IterableDeclContext *idc) const {
|
@@ -82,6 +160,9 @@ ParseMembersRequest::evaluate(Evaluator &evaluator,
|
82 | 160 | auto declsAndHash = parser.parseDeclListDelayed(idc);
|
83 | 161 | FingerprintAndMembers fingerprintAndMembers = {declsAndHash.second,
|
84 | 162 | declsAndHash.first};
|
| 163 | + |
| 164 | + registerDeclWithOpaqueResultType(sf->getOutermostParentSourceFile(), |
| 165 | + fingerprintAndMembers.members); |
85 | 166 | return FingerprintAndMembers{
|
86 | 167 | fingerprintAndMembers.fingerprint,
|
87 | 168 | ctx.AllocateCopy(llvm::ArrayRef(fingerprintAndMembers.members))};
|
@@ -134,6 +215,8 @@ ParseAbstractFunctionBodyRequest::evaluate(Evaluator &evaluator,
|
134 | 215 | Parser parser(bufferID, *sf, /*SIL*/ nullptr);
|
135 | 216 | auto result = parser.parseAbstractFunctionBodyDelayed(afd);
|
136 | 217 | afd->setBodyKind(BodyKind::Parsed);
|
| 218 | + registerDeclWithOpaqueResultType(afd->getOutermostParentSourceFile(), |
| 219 | + result.getBody()->getElements()); |
137 | 220 | return result;
|
138 | 221 | }
|
139 | 222 | }
|
@@ -312,6 +395,9 @@ SourceFileParsingResult parseSourceFileViaASTGen(SourceFile &SF) {
|
312 | 395 | fp = swift_ASTGen_getSourceFileFingerprint(exportedSourceFile, Ctx)
|
313 | 396 | .unbridged();
|
314 | 397 |
|
| 398 | + registerDeclWithOpaqueResultType(declContext->getOutermostParentSourceFile(), |
| 399 | + items); |
| 400 | + |
315 | 401 | return SourceFileParsingResult{/*TopLevelItems=*/Ctx.AllocateCopy(items),
|
316 | 402 | /*CollectedTokens=*/std::nullopt,
|
317 | 403 | /*Fingerprint=*/fp};
|
@@ -444,6 +530,9 @@ SourceFileParsingResult parseSourceFile(SourceFile &SF) {
|
444 | 530 | if (parser.CurrentTokenHash)
|
445 | 531 | fp = Fingerprint(std::move(*parser.CurrentTokenHash));
|
446 | 532 |
|
| 533 | + registerDeclWithOpaqueResultType( |
| 534 | + parser.CurDeclContext->getOutermostParentSourceFile(), items); |
| 535 | + |
447 | 536 | return SourceFileParsingResult{ctx.AllocateCopy(items), tokensRef, fp};
|
448 | 537 | }
|
449 | 538 |
|
|
0 commit comments