Skip to content

Commit acf6375

Browse files
committed
Introduce BindExtensionsForIDEInspectionRequest
This allows us to lazily bind extensions after mutating the AST, ensuring we don't prematurely kick the building of lookup tables.
1 parent 03dd5a2 commit acf6375

File tree

9 files changed

+55
-6
lines changed

9 files changed

+55
-6
lines changed

include/swift/AST/TypeCheckRequests.h

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

5392+
/// A request that allows IDE inspection to lazily kick extension binding after
5393+
/// it has finished mutating the AST. This will eventually be subsumed when we
5394+
/// properly requestify extension binding.
5395+
class BindExtensionsForIDEInspectionRequest
5396+
: public SimpleRequest<BindExtensionsForIDEInspectionRequest,
5397+
evaluator::SideEffect(ModuleDecl *),
5398+
RequestFlags::Cached> {
5399+
public:
5400+
using SimpleRequest::SimpleRequest;
5401+
5402+
private:
5403+
friend SimpleRequest;
5404+
5405+
evaluator::SideEffect evaluate(Evaluator &evaluator, ModuleDecl *M) const;
5406+
5407+
public:
5408+
bool isCached() const { return true; }
5409+
};
5410+
53925411
class ModuleHasTypeCheckerPerformanceHacksEnabledRequest
53935412
: public SimpleRequest<ModuleHasTypeCheckerPerformanceHacksEnabledRequest,
53945413
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, BindExtensionsForIDEInspectionRequest,
645+
evaluator::SideEffect(ModuleDecl *),
646+
Cached, NoLocationInfo)
647+
644648
SWIFT_REQUEST(TypeChecker, ModuleHasTypeCheckerPerformanceHacksEnabledRequest,
645649
bool(const ModuleDecl *),
646650
Cached, NoLocationInfo)

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
256256

257257
auto &newSF = newModule->getMainSourceFile();
258258
performImportResolution(newSF);
259-
bindExtensions(*newModule);
260259

261260
performIDEInspectionSecondPass(newSF, *CompletionCallbacksFactory);
262261

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
429429
// re-use imported modules.
430430
auto *newSF = &newM->getMainSourceFile();
431431
performImportResolution(*newSF);
432-
bindExtensions(*newM);
433432

434433
traceDC = newM;
435434
#ifndef NDEBUG
@@ -518,7 +517,8 @@ void IDEInspectionInstance::performNewOperation(
518517
CI->getASTContext().CancellationFlag = CancellationFlag;
519518
registerIDERequestFunctions(CI->getASTContext().evaluator);
520519

521-
CI->performParseAndResolveImportsOnly();
520+
CI->loadAccessNotesIfNeeded();
521+
performImportResolution(CI->getMainModule());
522522

523523
bool DidFindIDEInspectionTarget = CI->getIDEInspectionFile()
524524
->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+
// Bind extensions if needed. This needs to be done here since we may have
216+
// mutated the AST above.
217+
{
218+
auto *M = SF->getParentModule();
219+
BindExtensionsForIDEInspectionRequest req(M);
220+
evaluateOrDefault(Context.evaluator, req, {});
221+
}
222+
223+
DoneParsingCallback->doneParsing(SF);
213224

214225
State->restoreIDEInspectionDelayedDeclState(info);
215226
}

lib/Sema/TypeChecker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,3 +793,10 @@ std::pair<bool, bool> EvaluateIfConditionRequest::evaluate(
793793
llvm_unreachable("Must not be used in C++-only build");
794794
#endif
795795
}
796+
797+
evaluator::SideEffect
798+
BindExtensionsForIDEInspectionRequest::evaluate(Evaluator &evaluator,
799+
ModuleDecl *M) const {
800+
bindExtensions(*M);
801+
return {};
802+
}

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)