Skip to content

Commit 17fe3de

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 d9d0b2e commit 17fe3de

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
@@ -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

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
@@ -4002,11 +4002,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
40024002
return;
40034003
}
40044004

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

0 commit comments

Comments
 (0)