Skip to content

Commit f8218e3

Browse files
authored
Merge pull request #83777 from hamishknight/ext-cleanup
[Sema] Clean up extension binding a little
2 parents 872176b + d3be024 commit f8218e3

20 files changed

+131
-119
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,6 +2053,7 @@ class ExtensionDecl final : public GenericContext, public Decl,
20532053
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
20542054

20552055
friend class ExtendedNominalRequest;
2056+
friend class BindExtensionsRequest;
20562057
friend class Decl;
20572058
public:
20582059
using Decl::getASTContext;
@@ -2090,13 +2091,14 @@ class ExtensionDecl final : public GenericContext, public Decl,
20902091
Type getExtendedType() const;
20912092

20922093
/// Retrieve the nominal type declaration that is being extended.
2093-
/// Will trip an assertion if the declaration has not already been computed.
2094+
/// Will trip an assertion if the declaration has not already been computed.
20942095
/// In order to fail fast when type checking work is attempted
20952096
/// before extension binding has taken place.
2096-
20972097
NominalTypeDecl *getExtendedNominal() const;
20982098

2099-
/// Compute the nominal type declaration that is being extended.
2099+
/// Compute the nominal type declaration that is being extended. The result
2100+
/// is not cached, this should only be invoked by extension binding itself.
2101+
/// FIXME: Make this private once lldb has been migrated off it.
21002102
NominalTypeDecl *computeExtendedNominal(
21012103
bool excludeMacroExpansions=false) const;
21022104

include/swift/AST/NameLookupRequests.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ class HasMissingDesignatedInitializersRequest :
267267
/// Request the nominal declaration extended by a given extension declaration.
268268
class ExtendedNominalRequest
269269
: public SimpleRequest<
270-
ExtendedNominalRequest, NominalTypeDecl *(ExtensionDecl *, bool),
270+
ExtendedNominalRequest, NominalTypeDecl *(const ExtensionDecl *),
271271
RequestFlags::SeparatelyCached | RequestFlags::DependencySink> {
272272
public:
273273
using SimpleRequest::SimpleRequest;
@@ -276,8 +276,7 @@ class ExtendedNominalRequest
276276
friend SimpleRequest;
277277

278278
// Evaluation.
279-
NominalTypeDecl * evaluate(Evaluator &evaluator, ExtensionDecl *ext,
280-
bool excludeMacroExpansions) const;
279+
NominalTypeDecl * evaluate(Evaluator &evaluator, const ExtensionDecl *ext) const;
281280

282281
public:
283282
// Separate caching.

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ SWIFT_REQUEST(NameLookup, DirectPrecedenceGroupLookupRequest,
3232
TinyPtrVector<PrecedenceGroupDecl *>(OperatorLookupDescriptor),
3333
Uncached, NoLocationInfo)
3434
SWIFT_REQUEST(NameLookup, ExtendedNominalRequest,
35-
NominalTypeDecl *(ExtensionDecl *), SeparatelyCached,
35+
NominalTypeDecl *(const ExtensionDecl *), SeparatelyCached,
3636
NoLocationInfo)
3737
SWIFT_REQUEST(NameLookup, GenericParamListRequest,
3838
GenericParamList *(GenericContext *), SeparatelyCached,

include/swift/AST/TypeCheckRequests.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5437,11 +5437,9 @@ class DefaultIsolationInSourceFileRequest
54375437
bool isCached() const { return true; }
54385438
};
54395439

5440-
/// A request that allows IDE inspection to lazily kick extension binding after
5441-
/// it has finished mutating the AST. This will eventually be subsumed when we
5442-
/// properly requestify extension binding.
5443-
class BindExtensionsForIDEInspectionRequest
5444-
: public SimpleRequest<BindExtensionsForIDEInspectionRequest,
5440+
/// Performs extension binding for all of the extensions in a module.
5441+
class BindExtensionsRequest
5442+
: public SimpleRequest<BindExtensionsRequest,
54455443
evaluator::SideEffect(ModuleDecl *),
54465444
RequestFlags::Cached> {
54475445
public:

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ SWIFT_REQUEST(TypeChecker, DefaultIsolationInSourceFileRequest,
647647
std::optional<DefaultIsolation>(const SourceFile *),
648648
Cached, NoLocationInfo)
649649

650-
SWIFT_REQUEST(TypeChecker, BindExtensionsForIDEInspectionRequest,
650+
SWIFT_REQUEST(TypeChecker, BindExtensionsRequest,
651651
evaluator::SideEffect(ModuleDecl *),
652652
Cached, NoLocationInfo)
653653

include/swift/Sema/SourceLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ModuleDecl;
2424
class SourceLoader : public ModuleLoader {
2525
private:
2626
ASTContext &Ctx;
27+
std::vector<ModuleDecl *> ModulesToBindExtensions;
2728
bool EnableLibraryEvolution;
2829

2930
explicit SourceLoader(ASTContext &ctx,

lib/AST/Decl.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,24 +2097,8 @@ ExtensionDecl::takeConformanceLoaderSlow() {
20972097
}
20982098

20992099
NominalTypeDecl *ExtensionDecl::getExtendedNominal() const {
2100-
if (hasBeenBound()) {
2101-
return ExtendedNominal.getPointer();
2102-
} else if (canNeverBeBound()) {
2103-
return computeExtendedNominal();
2104-
}
2105-
2106-
llvm_unreachable(
2107-
"Extension must have already been bound (by bindExtensions)");
2108-
}
2109-
2110-
NominalTypeDecl *ExtensionDecl::computeExtendedNominal(
2111-
bool excludeMacroExpansions) const {
2112-
ASTContext &ctx = getASTContext();
2113-
return evaluateOrDefault(ctx.evaluator,
2114-
ExtendedNominalRequest{
2115-
const_cast<ExtensionDecl *>(this),
2116-
excludeMacroExpansions},
2117-
nullptr);
2100+
auto &eval = getASTContext().evaluator;
2101+
return evaluateOrDefault(eval, ExtendedNominalRequest{this}, nullptr);
21182102
}
21192103

21202104
bool ExtensionDecl::canNeverBeBound() const {

lib/AST/NameLookup.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3583,20 +3583,19 @@ ProtocolRequirementsRequest::evaluate(Evaluator &evaluator,
35833583
return PD->getASTContext().AllocateCopy(requirements);
35843584
}
35853585

3586-
NominalTypeDecl *
3587-
ExtendedNominalRequest::evaluate(Evaluator &evaluator,
3588-
ExtensionDecl *ext,
3589-
bool excludeMacroExpansions) const {
3590-
auto typeRepr = ext->getExtendedTypeRepr();
3586+
NominalTypeDecl *ExtensionDecl::computeExtendedNominal(
3587+
bool excludeMacroExpansions) const {
3588+
auto typeRepr = getExtendedTypeRepr();
35913589
if (!typeRepr) {
35923590
// We must've seen 'extension { ... }' during parsing.
35933591
return nullptr;
35943592
}
35953593

3596-
ASTContext &ctx = ext->getASTContext();
3594+
ASTContext &ctx = getASTContext();
3595+
auto &evaluator = ctx.evaluator;
35973596
auto options = defaultDirectlyReferencedTypeLookupOptions;
35983597

3599-
if (ext->isInSpecializeExtensionContext()) {
3598+
if (isInSpecializeExtensionContext()) {
36003599
options |= DirectlyReferencedTypeLookupFlags::AllowUsableFromInline;
36013600
}
36023601

@@ -3605,7 +3604,7 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
36053604
}
36063605

36073606
DirectlyReferencedTypeDecls referenced = directReferencesForTypeRepr(
3608-
evaluator, ctx, typeRepr, ext->getParent(), options);
3607+
evaluator, ctx, typeRepr, getParent(), options);
36093608

36103609
// If there were no results, expand the lookup to include members that are
36113610
// inaccessible due to missing imports. The missing imports will be diagnosed
@@ -3615,7 +3614,7 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
36153614
/*allowMigration=*/true)) {
36163615
options |= DirectlyReferencedTypeLookupFlags::IgnoreMissingImports;
36173616
referenced = directReferencesForTypeRepr(evaluator, ctx, typeRepr,
3618-
ext->getParent(), options);
3617+
getParent(), options);
36193618
}
36203619

36213620
// Resolve those type declarations to nominal type declarations.
@@ -3634,6 +3633,13 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
36343633
return nominalTypes[0];
36353634
}
36363635

3636+
NominalTypeDecl *
3637+
ExtendedNominalRequest::evaluate(Evaluator &evaluator,
3638+
const ExtensionDecl *ext) const {
3639+
ASSERT(ext->canNeverBeBound() && "Should have been bound by bindExtensions");
3640+
return ext->computeExtendedNominal();
3641+
}
3642+
36373643
/// Whether there are only associated types in the set of declarations.
36383644
static bool declsAreAssociatedTypes(ArrayRef<TypeDecl *> decls) {
36393645
if (decls.empty())

lib/AST/NameLookupRequests.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,22 +205,15 @@ HasMissingDesignatedInitializersRequest::evaluate(Evaluator &evaluator,
205205

206206
std::optional<NominalTypeDecl *>
207207
ExtendedNominalRequest::getCachedResult() const {
208-
// Note: if we fail to compute any nominal declaration, it's considered
209-
// a cache miss. This allows us to recompute the extended nominal types
210-
// during extension binding.
211-
// This recomputation is also what allows you to extend types defined inside
212-
// other extensions, regardless of source file order. See \c bindExtensions(),
213-
// which uses a worklist algorithm that attempts to bind everything until
214-
// fixed point.
215208
auto ext = std::get<0>(getStorage());
216-
if (!ext->hasBeenBound() || !ext->getExtendedNominal())
209+
if (!ext->hasBeenBound())
217210
return std::nullopt;
218-
return ext->getExtendedNominal();
211+
return ext->ExtendedNominal.getPointer();
219212
}
220213

221214
void ExtendedNominalRequest::cacheResult(NominalTypeDecl *value) const {
222215
auto ext = std::get<0>(getStorage());
223-
ext->setExtendedNominal(value);
216+
const_cast<ExtensionDecl *>(ext)->setExtendedNominal(value);
224217
}
225218

226219
void ExtendedNominalRequest::writeDependencySink(

lib/IDE/CodeCompletion.cpp

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "CodeCompletionDiagnostics.h"
1515
#include "CodeCompletionResultBuilder.h"
1616
#include "ExprContextAnalysis.h"
17+
#include "ReadyForTypeCheckingCallback.h"
1718
#include "swift/AST/ASTPrinter.h"
1819
#include "swift/AST/ASTWalker.h"
1920
#include "swift/AST/Comment.h"
@@ -105,7 +106,7 @@ std::string swift::ide::removeCodeCompletionTokens(
105106
namespace {
106107

107108
class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
108-
public DoneParsingCallback {
109+
public ReadyForTypeCheckingCallback {
109110
CodeCompletionContext &CompletionContext;
110111
CodeCompletionConsumer &Consumer;
111112
CodeCompletionExpr *CodeCompleteTokenExpr = nullptr;
@@ -175,25 +176,6 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
175176

176177
/// \returns true on success, false on failure.
177178
bool typecheckParsedType() {
178-
// If the type appeared inside an extension, make sure that extension has
179-
// been bound.
180-
auto SF = CurDeclContext->getParentSourceFile();
181-
auto visitTopLevelDecl = [&](Decl *D) {
182-
if (auto ED = dyn_cast<ExtensionDecl>(D)) {
183-
if (ED->getSourceRange().contains(ParsedTypeLoc.getLoc())) {
184-
ED->computeExtendedNominal();
185-
}
186-
}
187-
};
188-
for (auto item : SF->getTopLevelItems()) {
189-
if (auto D = item.dyn_cast<Decl *>()) {
190-
visitTopLevelDecl(D);
191-
}
192-
}
193-
for (auto *D : SF->getHoistedDecls()) {
194-
visitTopLevelDecl(D);
195-
}
196-
197179
assert(ParsedTypeLoc.getTypeRepr() && "should have a TypeRepr");
198180
if (ParsedTypeLoc.wasValidated() && !ParsedTypeLoc.isError()) {
199181
return true;
@@ -233,8 +215,8 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
233215
CodeCompletionCallbacksImpl(Parser &P,
234216
CodeCompletionContext &CompletionContext,
235217
CodeCompletionConsumer &Consumer)
236-
: CodeCompletionCallbacks(P), DoneParsingCallback(),
237-
CompletionContext(CompletionContext), Consumer(Consumer) {}
218+
: CodeCompletionCallbacks(P), CompletionContext(CompletionContext),
219+
Consumer(Consumer) {}
238220

239221
void setAttrTargetDeclKind(std::optional<DeclKind> DK) override {
240222
if (DK == DeclKind::PatternBinding)
@@ -309,7 +291,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
309291
void completeTypeAttrInheritanceBeginning() override;
310292
void completeOptionalBinding() override;
311293

312-
void doneParsing(SourceFile *SrcFile) override;
294+
void readyForTypeChecking(SourceFile *SrcFile) override;
313295

314296
private:
315297
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
@@ -1641,7 +1623,7 @@ void CodeCompletionCallbacksImpl::afterPoundCompletion(SourceLoc CompletionLoc,
16411623
Consumer.handleResults(CompletionContext);
16421624
}
16431625

1644-
void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
1626+
void CodeCompletionCallbacksImpl::readyForTypeChecking(SourceFile *SrcFile) {
16451627
CompletionContext.CodeCompletionKind = Kind;
16461628

16471629
if (Kind == CompletionKind::None) {

0 commit comments

Comments
 (0)