Skip to content

Commit 01d4440

Browse files
committed
Funnel all "get local conformances" queries through a request.
LookupAllConformancesInContextRequest caches the results of performing lookup of all of the conformances ascribed to a given iterable declaration context. However, it was only used in a small number of places, with most clients using a different API (`getLocalConformances()`) that does not provide caching, cycle detection, or dependency tracking. Sink LookupAllConformancesInContextRequest lower in the stack, and reimplement `getLocalConformances()` on top of it. This ensures that all of the various queries go through the cached request and get the benefits of the request-evaluator infrastructure.
1 parent dcd3c6f commit 01d4440

File tree

6 files changed

+63
-32
lines changed

6 files changed

+63
-32
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,7 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
30043004
friend class DeclContext;
30053005
friend class IterableDeclContext;
30063006
friend class DirectLookupRequest;
3007+
friend class LookupAllConformancesInContextRequest;
30073008
friend ArrayRef<ValueDecl *>
30083009
ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const;
30093010

include/swift/AST/DeclContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ class IterableDeclContext {
734734

735735
static IterableDeclContext *castDeclToIterableDeclContext(const Decl *D);
736736

737+
friend class LookupAllConformancesInContextRequest;
738+
737739
/// Retrieve the \c ASTContext in which this iterable context occurs.
738740
ASTContext &getASTContext() const;
739741

lib/AST/ProtocolConformance.cpp

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,38 +1342,81 @@ IterableDeclContext::getLocalProtocols(ConformanceLookupKind lookupKind) const {
13421342
return result;
13431343
}
13441344

1345-
SmallVector<ProtocolConformance *, 2>
1346-
IterableDeclContext::getLocalConformances(ConformanceLookupKind lookupKind)
1347-
const {
1348-
SmallVector<ProtocolConformance *, 2> result;
1349-
1345+
std::vector<ProtocolConformance *>
1346+
LookupAllConformancesInContextRequest::evaluate(
1347+
Evaluator &eval, const IterableDeclContext *IDC) const {
13501348
// Dig out the nominal type.
1351-
const auto dc = getAsGenericContext();
1349+
const auto dc = IDC->getAsGenericContext();
13521350
const auto nominal = dc->getSelfNominalTypeDecl();
13531351
if (!nominal) {
1354-
return result;
1352+
return { };
13551353
}
13561354

13571355
// Protocols only have self-conformances.
13581356
if (auto protocol = dyn_cast<ProtocolDecl>(nominal)) {
13591357
if (protocol->requiresSelfConformanceWitnessTable()) {
1360-
return SmallVector<ProtocolConformance *, 2>{
1361-
protocol->getASTContext().getSelfConformance(protocol)
1362-
};
1358+
return { protocol->getASTContext().getSelfConformance(protocol) };
13631359
}
1364-
return SmallVector<ProtocolConformance *, 2>();
1360+
1361+
return { };
13651362
}
13661363

13671364
// Update to record all potential conformances.
13681365
nominal->prepareConformanceTable();
1366+
SmallVector<ProtocolConformance *, 4> conformances;
13691367
nominal->ConformanceTable->lookupConformances(
13701368
nominal,
13711369
const_cast<GenericContext *>(dc),
1372-
lookupKind,
1370+
ConformanceLookupKind::All,
13731371
nullptr,
1374-
&result,
1372+
&conformances,
13751373
nullptr);
13761374

1375+
return std::vector<ProtocolConformance *>(
1376+
conformances.begin(), conformances.end());
1377+
}
1378+
1379+
SmallVector<ProtocolConformance *, 2>
1380+
IterableDeclContext::getLocalConformances(ConformanceLookupKind lookupKind)
1381+
const {
1382+
// Look up the cached set of all of the conformances.
1383+
std::vector<ProtocolConformance *> conformances =
1384+
evaluateOrDefault(
1385+
getASTContext().evaluator, LookupAllConformancesInContextRequest{this},
1386+
{ });
1387+
1388+
// Copy all of the conformances we want.
1389+
SmallVector<ProtocolConformance *, 2> result;
1390+
std::copy_if(
1391+
conformances.begin(), conformances.end(), std::back_inserter(result),
1392+
[&](ProtocolConformance *conformance) {
1393+
// If we are to filter out this result, do so now.
1394+
switch (lookupKind) {
1395+
case ConformanceLookupKind::OnlyExplicit:
1396+
switch (conformance->getSourceKind()) {
1397+
case ConformanceEntryKind::Explicit:
1398+
case ConformanceEntryKind::Synthesized:
1399+
return true;
1400+
case ConformanceEntryKind::Implied:
1401+
case ConformanceEntryKind::Inherited:
1402+
return false;
1403+
}
1404+
1405+
case ConformanceLookupKind::NonInherited:
1406+
switch (conformance->getSourceKind()) {
1407+
case ConformanceEntryKind::Explicit:
1408+
case ConformanceEntryKind::Synthesized:
1409+
case ConformanceEntryKind::Implied:
1410+
return true;
1411+
case ConformanceEntryKind::Inherited:
1412+
return false;
1413+
}
1414+
1415+
case ConformanceLookupKind::All:
1416+
return true;
1417+
}
1418+
});
1419+
13771420
return result;
13781421
}
13791422

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,7 @@ bool IsAsyncHandlerRequest::evaluate(
178178
// implies @asyncHandler.
179179
{
180180
auto idc = cast<IterableDeclContext>(dc->getAsDecl());
181-
auto conformances = evaluateOrDefault(
182-
dc->getASTContext().evaluator,
183-
LookupAllConformancesInContextRequest{idc}, { });
181+
auto conformances = idc->getLocalConformances();
184182

185183
for (auto conformance : conformances) {
186184
auto protocol = conformance->getProtocol();
@@ -2050,9 +2048,7 @@ static Optional<ActorIsolation> getIsolationFromWitnessedRequirements(
20502048

20512049
// Walk through each of the conformances in this context, collecting any
20522050
// requirements that have actor isolation.
2053-
auto conformances = evaluateOrDefault(
2054-
dc->getASTContext().evaluator,
2055-
LookupAllConformancesInContextRequest{idc}, { });
2051+
auto conformances = idc->getLocalConformances();
20562052
using IsolatedRequirement =
20572053
std::tuple<ProtocolConformance *, ActorIsolation, ValueDecl *>;
20582054
SmallVector<IsolatedRequirement, 2> isolatedRequirements;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5650,13 +5650,6 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) {
56505650
}
56515651
}
56525652

5653-
std::vector<ProtocolConformance *>
5654-
LookupAllConformancesInContextRequest::evaluate(
5655-
Evaluator &eval, const IterableDeclContext *IDC) const {
5656-
auto result = IDC->getLocalConformances(ConformanceLookupKind::All);
5657-
return std::vector<ProtocolConformance *>(result.begin(), result.end());
5658-
}
5659-
56605653
void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
56615654
auto *const dc = idc->getAsGenericContext();
56625655

@@ -5672,9 +5665,7 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
56725665
const auto defaultAccess = nominal->getFormalAccess();
56735666

56745667
// Check each of the conformances associated with this context.
5675-
auto conformances =
5676-
evaluateOrDefault(dc->getASTContext().evaluator,
5677-
LookupAllConformancesInContextRequest{idc}, {});
5668+
auto conformances = idc->getLocalConformances();
56785669

56795670
// The conformance checker bundle that checks all conformances in the context.
56805671
auto &Context = dc->getASTContext();

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,7 @@ static Type inferResultBuilderType(ValueDecl *decl) {
274274
auto addConformanceMatches = [&matches](ValueDecl *lookupDecl) {
275275
DeclContext *dc = lookupDecl->getDeclContext();
276276
auto idc = cast<IterableDeclContext>(dc->getAsDecl());
277-
auto conformances = evaluateOrDefault(
278-
dc->getASTContext().evaluator,
279-
LookupAllConformancesInContextRequest{idc}, { });
277+
auto conformances = idc->getLocalConformances();
280278

281279
for (auto conformance : conformances) {
282280
auto protocol = conformance->getProtocol();

0 commit comments

Comments
 (0)