Skip to content

Commit 4de729f

Browse files
committed
[NFC] Add LookupConformancesInContextRequest
Add a request to lookup all implied conformances for use while typechecking the primary. This provides a cache-point for evaluator-based dependency tracking.
1 parent a9e11e3 commit 4de729f

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,39 @@ class ClosureHasExplicitResultRequest
21602160
bool isCached() const { return true; }
21612161
};
21622162

2163+
using ProtocolConformanceLookupResult = SmallVector<ProtocolConformance *, 2>;
2164+
void simple_display(llvm::raw_ostream &out, ConformanceLookupKind kind);
2165+
2166+
/// Lookup and expand all conformances in the given context.
2167+
///
2168+
/// This request specifically accomodates algorithms for retrieving all
2169+
/// conformances in the primary, even those that are unstated in source but
2170+
/// are implied by other conformances, inherited from other types, or synthesized
2171+
/// by the compiler. A simple case of this is the following:
2172+
///
2173+
/// \code
2174+
/// protocol P {}
2175+
/// protocol Q : P {}
2176+
/// extension T : Q {}
2177+
/// \endcode
2178+
///
2179+
/// Here, a conformance to \c Q has been stated, but a conformance to \c P
2180+
/// must also be reported so it can be checked as well.
2181+
class LookupAllConformancesInContextRequest :
2182+
public SimpleRequest<LookupAllConformancesInContextRequest,
2183+
ProtocolConformanceLookupResult(const DeclContext *),
2184+
CacheKind::Uncached> {
2185+
public:
2186+
using SimpleRequest::SimpleRequest;
2187+
2188+
private:
2189+
friend SimpleRequest;
2190+
2191+
// Evaluation.
2192+
llvm::Expected<ProtocolConformanceLookupResult>
2193+
evaluate(Evaluator &evaluator, const DeclContext *DC) const;
2194+
};
2195+
21632196
// Allow AnyValue to compare two Type values, even though Type doesn't
21642197
// support ==.
21652198
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,6 @@ SWIFT_REQUEST(TypeChecker, ScopedImportLookupRequest,
234234
ArrayRef<ValueDecl *>(ImportDecl *), Cached, NoLocationInfo)
235235
SWIFT_REQUEST(TypeChecker, ClosureHasExplicitResultRequest,
236236
bool(ClosureExpr *), Cached, NoLocationInfo)
237+
SWIFT_REQUEST(TypeChecker, LookupAllConformancesInContextRequest,
238+
ProtocolConformanceLookupResult(const DeclContext *),
239+
Uncached, NoLocationInfo)

lib/AST/ProtocolConformance.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ DeclContext::getLocalProtocols(ConformanceLookupKind lookupKind) const {
13351335
if (!nominal) {
13361336
return result;
13371337
}
1338-
1338+
13391339
// Update to record all potential conformances.
13401340
nominal->prepareConformanceTable();
13411341
nominal->ConformanceTable->lookupConformances(
@@ -1361,9 +1361,12 @@ DeclContext::getLocalConformances(ConformanceLookupKind lookupKind) const {
13611361

13621362
// Protocols only have self-conformances.
13631363
if (auto protocol = dyn_cast<ProtocolDecl>(nominal)) {
1364-
if (protocol->requiresSelfConformanceWitnessTable())
1365-
return { protocol->getASTContext().getSelfConformance(protocol) };
1366-
return { };
1364+
if (protocol->requiresSelfConformanceWitnessTable()) {
1365+
return SmallVector<ProtocolConformance *, 2>{
1366+
protocol->getASTContext().getSelfConformance(protocol)
1367+
};
1368+
}
1369+
return SmallVector<ProtocolConformance *, 2>();
13671370
}
13681371

13691372
// Update to record all potential conformances.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5011,6 +5011,12 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) {
50115011
}
50125012
}
50135013

5014+
llvm::Expected<SmallVector<ProtocolConformance *, 2>>
5015+
LookupAllConformancesInContextRequest::evaluate(
5016+
Evaluator &eval, const DeclContext *DC) const {
5017+
return DC->getLocalConformances(ConformanceLookupKind::All);
5018+
}
5019+
50145020
void TypeChecker::checkConformancesInContext(DeclContext *dc,
50155021
IterableDeclContext *idc) {
50165022
// For anything imported from Clang, lazily check conformances.
@@ -5037,7 +5043,9 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
50375043
tracker = SF->getReferencedNameTracker();
50385044

50395045
// Check each of the conformances associated with this context.
5040-
auto conformances = dc->getLocalConformances(ConformanceLookupKind::All);
5046+
auto conformances =
5047+
evaluateOrDefault(dc->getASTContext().evaluator,
5048+
LookupAllConformancesInContextRequest{dc}, {});
50415049

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

0 commit comments

Comments
 (0)