Skip to content

Commit 6c649cb

Browse files
committed
[Sema] Clean up extension binding a little
- Turn `BindExtensionsForIDEInspectionRequest` into the main extension binding request. - Change `ExtendedNominalRequest` such that it's no longer what extension binding calls into to do the name lookup, instead it calls directly into `computeExtendedNominal`. `getExtendedNominal` can then be the entrypoint for `ExtendedNominalRequest` and assumes that extension binding has already run. This avoids needing to fake the dependency relationship in the DeclChecker.
1 parent 7bd83bc commit 6c649cb

11 files changed

+46
-69
lines changed

include/swift/AST/Decl.h

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

20442044
friend class ExtendedNominalRequest;
2045+
friend class BindExtensionsRequest;
20452046
friend class Decl;
20462047
public:
20472048
using Decl::getASTContext;
@@ -2079,13 +2080,14 @@ class ExtensionDecl final : public GenericContext, public Decl,
20792080
Type getExtendedType() const;
20802081

20812082
/// Retrieve the nominal type declaration that is being extended.
2082-
/// Will trip an assertion if the declaration has not already been computed.
2083+
/// Will trip an assertion if the declaration has not already been computed.
20832084
/// In order to fail fast when type checking work is attempted
20842085
/// before extension binding has taken place.
2085-
20862086
NominalTypeDecl *getExtendedNominal() const;
20872087

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

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
@@ -5389,11 +5389,9 @@ 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,
5392+
/// Performs extension binding for all of the extensions in a module.
5393+
class BindExtensionsRequest
5394+
: public SimpleRequest<BindExtensionsRequest,
53975395
evaluator::SideEffect(ModuleDecl *),
53985396
RequestFlags::Cached> {
53995397
public:

include/swift/AST/TypeCheckerTypeIDZone.def

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

644-
SWIFT_REQUEST(TypeChecker, BindExtensionsForIDEInspectionRequest,
644+
SWIFT_REQUEST(TypeChecker, BindExtensionsRequest,
645645
evaluator::SideEffect(ModuleDecl *),
646646
Cached, NoLocationInfo)
647647

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/Parse/Parser.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,7 @@ void Parser::performIDEInspectionSecondPassImpl(
214214

215215
// Bind extensions if needed. This needs to be done here since we may have
216216
// mutated the AST above.
217-
{
218-
auto *M = SF->getParentModule();
219-
BindExtensionsForIDEInspectionRequest req(M);
220-
evaluateOrDefault(Context.evaluator, req, {});
221-
}
217+
bindExtensions(*SF->getParentModule());
222218

223219
DoneParsingCallback->doneParsing(SF);
224220

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4003,11 +4003,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
40034003
return;
40044004
}
40054005

4006-
// Record a dependency from TypeCheckPrimaryFileRequest to
4007-
// ExtendedNominalRequest, since the call to getExtendedNominal()
4008-
// above doesn't record a dependency when reading a cached value.
4009-
ED->computeExtendedNominal();
4010-
40114006
if (!extType->hasError()) {
40124007
// The first condition catches syntactic forms like
40134008
// protocol A & B { ... } // may be protocols or typealiases

0 commit comments

Comments
 (0)