Skip to content

Commit 19ee72e

Browse files
committed
Introduce ResolveImportsAndBindExtensionsForIDEInspectionRequest
This allows us to lazily resolve imports and bind extensions after mutating the AST, ensuring we don't prematurely kick the building of lookup tables.
1 parent 220e5a7 commit 19ee72e

File tree

9 files changed

+61
-13
lines changed

9 files changed

+61
-13
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5389,6 +5389,26 @@ class DefaultIsolationInSourceFileRequest
53895389
bool isCached() const { return true; }
53905390
};
53915391

5392+
/// A request that allows IDE inspection to lazily kick import resolution and
5393+
/// extension binding after it has finished mutating the AST. This will
5394+
/// eventually be subsumed when we requestify import resolution and extension
5395+
/// binding.
5396+
class ResolveImportsAndBindExtensionsForIDEInspectionRequest
5397+
: public SimpleRequest<
5398+
ResolveImportsAndBindExtensionsForIDEInspectionRequest,
5399+
evaluator::SideEffect(ModuleDecl *), RequestFlags::Cached> {
5400+
public:
5401+
using SimpleRequest::SimpleRequest;
5402+
5403+
private:
5404+
friend SimpleRequest;
5405+
5406+
evaluator::SideEffect evaluate(Evaluator &evaluator, ModuleDecl *M) const;
5407+
5408+
public:
5409+
bool isCached() const { return true; }
5410+
};
5411+
53925412
class ModuleHasTypeCheckerPerformanceHacksEnabledRequest
53935413
: public SimpleRequest<ModuleHasTypeCheckerPerformanceHacksEnabledRequest,
53945414
bool(const ModuleDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,10 @@ SWIFT_REQUEST(TypeChecker, DefaultIsolationInSourceFileRequest,
641641
std::optional<DefaultIsolation>(const SourceFile *),
642642
Cached, NoLocationInfo)
643643

644+
SWIFT_REQUEST(TypeChecker, ResolveImportsAndBindExtensionsForIDEInspectionRequest,
645+
evaluator::SideEffect(ModuleDecl *),
646+
Cached, NoLocationInfo)
647+
644648
SWIFT_REQUEST(TypeChecker, ModuleHasTypeCheckerPerformanceHacksEnabledRequest,
645649
bool(const ModuleDecl *),
646650
Cached, NoLocationInfo)

lib/IDE/IDETypeChecking.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/IDE/SourceEntityWalker.h"
3333
#include "swift/Parse/Lexer.h"
3434
#include "swift/Sema/IDETypeCheckingRequests.h"
35+
#include "swift/Subsystems.h"
3536
#include "llvm/ADT/SmallVector.h"
3637

3738
using namespace swift;
@@ -1048,3 +1049,11 @@ swift::getShorthandShadows(LabeledConditionalStmt *CondStmt, DeclContext *DC) {
10481049
}
10491050
return Result;
10501051
}
1052+
1053+
evaluator::SideEffect
1054+
ResolveImportsAndBindExtensionsForIDEInspectionRequest::evaluate(
1055+
Evaluator &evaluator, ModuleDecl *M) const {
1056+
performImportResolution(M);
1057+
bindExtensions(*M);
1058+
return {};
1059+
}

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,8 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
254254
addFile(new (Ctx) SourceFile(*newModule, SourceFileKind::Main, *BufferID));
255255
});
256256

257-
auto &newSF = newModule->getMainSourceFile();
258-
performImportResolution(newSF);
259-
bindExtensions(*newModule);
260-
261-
performIDEInspectionSecondPass(newSF, *CompletionCallbacksFactory);
257+
performIDEInspectionSecondPass(newModule->getMainSourceFile(),
258+
*CompletionCallbacksFactory);
262259

263260
// Reset the error state because it's only relevant to the code that we just
264261
// processed, which now gets thrown away.

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,9 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
425425
// Tell the compiler instance we've replaced the main module.
426426
CachedCI->setMainModule(newM);
427427

428-
// Re-process the whole file (parsing will be lazily triggered). Still
429-
// re-use imported modules.
428+
// Re-parse the SourceFile.
430429
auto *newSF = &newM->getMainSourceFile();
431-
performImportResolution(*newSF);
432-
bindExtensions(*newM);
430+
(void)newSF->getTopLevelItems();
433431

434432
traceDC = newM;
435433
#ifndef NDEBUG
@@ -518,7 +516,7 @@ void IDEInspectionInstance::performNewOperation(
518516
CI->getASTContext().CancellationFlag = CancellationFlag;
519517
registerIDERequestFunctions(CI->getASTContext().evaluator);
520518

521-
CI->performParseAndResolveImportsOnly();
519+
CI->loadAccessNotesIfNeeded();
522520

523521
bool DidFindIDEInspectionTarget = CI->getIDEInspectionFile()
524522
->getDelayedParserState()

lib/Parse/Parser.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ void Parser::performIDEInspectionSecondPassImpl(
162162
// Clear any ASTScopes that were expanded.
163163
SF.clearScope();
164164

165+
// FIXME: We shouldn't be mutating the AST after-the-fact like this.
165166
switch (info.Kind) {
166167
case IDEInspectionDelayedDeclKind::TopLevelCodeDecl: {
167168
// Re-enter the top-level code decl context.
@@ -209,7 +210,17 @@ void Parser::performIDEInspectionSecondPassImpl(
209210
assert(!State->hasIDEInspectionDelayedDeclState() &&
210211
"Second pass should not set any code completion info");
211212

212-
DoneParsingCallback->doneParsing(DC->getParentSourceFile());
213+
auto *SF = DC->getParentSourceFile();
214+
215+
// Resolve imports and bind extensions if needed. This needs to be done here
216+
// since we may have mutated the AST above.
217+
{
218+
auto *M = SF->getParentModule();
219+
ResolveImportsAndBindExtensionsForIDEInspectionRequest req(M);
220+
evaluateOrDefault(Context.evaluator, req, {});
221+
}
222+
223+
DoneParsingCallback->doneParsing(SF);
213224

214225
State->restoreIDEInspectionDelayedDeclState(info);
215226
}

test/IDE/pr83369.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %batch-code-completion -module-name main
2+
3+
extension Int {}
4+
5+
// Make sure we can resolve P here.
6+
protocol P<X> where X: main.#^COMPLETE^# {
7+
associatedtype X
8+
}
9+
// COMPLETE: Decl[Protocol]/CurrModule: P[#P#]; name=P
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"complete","original":"0b319c77","signature":"swift::ExtensionDecl::getExtendedNominal() const","signatureAssert":"Extension must have already been bound"}
2-
// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
2+
// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
33
extension a[ {
44
#^^#
55
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// {"kind":"complete","signature":"Extension must have already been bound","signatureAssert":"Extension must have already been bound"}
2-
// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
2+
// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
33
extension a [ { func b {
44
#^COMPLETE^#

0 commit comments

Comments
 (0)