Skip to content

Commit d4bc0a6

Browse files
committed
[NFC] Define LookupConformanceInModuleRequest
Factor out the lookup side of TypeChecker::conformsToProtocol so we have a dependency registration point available for evaluator-based dependencies that doesn't have re-entrancy problems.
1 parent 89b8163 commit d4bc0a6

File tree

4 files changed

+85
-6
lines changed

4 files changed

+85
-6
lines changed

include/swift/AST/NameLookupRequests.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,51 @@ class DirectPrecedenceGroupLookupRequest
632632
evaluate(Evaluator &evaluator, OperatorLookupDescriptor descriptor) const;
633633
};
634634

635+
class LookupConformanceDescriptor final {
636+
public:
637+
ModuleDecl *Mod;
638+
Type Ty;
639+
ProtocolDecl *PD;
640+
641+
LookupConformanceDescriptor(ModuleDecl *Mod, Type Ty, ProtocolDecl *PD)
642+
: Mod(Mod), Ty(Ty), PD(PD) {}
643+
644+
friend llvm::hash_code hash_value(const LookupConformanceDescriptor &desc) {
645+
return llvm::hash_combine(desc.Mod, desc.Ty.getPointer(), desc.PD);
646+
}
647+
648+
friend bool operator==(const LookupConformanceDescriptor &lhs,
649+
const LookupConformanceDescriptor &rhs) {
650+
return lhs.Mod == rhs.Mod && lhs.Ty.getPointer() == rhs.Ty.getPointer() &&
651+
lhs.PD == rhs.PD;
652+
}
653+
654+
friend bool operator!=(const LookupConformanceDescriptor &lhs,
655+
const LookupConformanceDescriptor &rhs) {
656+
return !(lhs == rhs);
657+
}
658+
};
659+
660+
void simple_display(llvm::raw_ostream &out,
661+
const LookupConformanceDescriptor &desc);
662+
663+
SourceLoc extractNearestSourceLoc(const LookupConformanceDescriptor &desc);
664+
665+
class LookupConformanceInModuleRequest
666+
: public SimpleRequest<LookupConformanceInModuleRequest,
667+
ProtocolConformanceRef(LookupConformanceDescriptor),
668+
CacheKind::Uncached> {
669+
public:
670+
using SimpleRequest::SimpleRequest;
671+
672+
private:
673+
friend SimpleRequest;
674+
675+
// Evaluation.
676+
llvm::Expected<ProtocolConformanceRef> evaluate(
677+
Evaluator &evaluator, LookupConformanceDescriptor desc) const;
678+
};
679+
635680
#define SWIFT_TYPEID_ZONE NameLookup
636681
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
637682
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ SWIFT_REQUEST(NameLookup, InheritedDeclsReferencedRequest,
4747
DirectlyReferencedTypeDecls(
4848
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>, unsigned),
4949
Uncached, HasNearestLocation)
50+
SWIFT_REQUEST(NameLookup, LookupConformanceInModuleRequest,
51+
ProtocolConformanceRef(LookupConformanceDescriptor),
52+
Uncached, NoLocationInfo)
5053
SWIFT_REQUEST(NameLookup, LookupInModuleRequest,
5154
QualifiedLookupResult(const DeclContext *, DeclName, NLKind,
5255
namelookup::ResolutionKind,

lib/AST/Module.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,19 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
821821

822822
ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
823823
ProtocolDecl *protocol) {
824-
ASTContext &ctx = getASTContext();
824+
return evaluateOrDefault(
825+
getASTContext().evaluator,
826+
LookupConformanceInModuleRequest{{this, type, protocol}},
827+
ProtocolConformanceRef::forInvalid());
828+
}
829+
830+
llvm::Expected<ProtocolConformanceRef>
831+
LookupConformanceInModuleRequest::evaluate(
832+
Evaluator &evaluator, LookupConformanceDescriptor desc) const {
833+
auto *mod = desc.Mod;
834+
auto type = desc.Ty;
835+
auto protocol = desc.PD;
836+
ASTContext &ctx = mod->getASTContext();
825837

826838
// A dynamic Self type conforms to whatever its underlying type
827839
// conforms to.
@@ -839,7 +851,7 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
839851
// able to be resolved by a substitution that makes the archetype
840852
// concrete.
841853
if (auto super = archetype->getSuperclass()) {
842-
if (auto inheritedConformance = lookupConformance(super, protocol)) {
854+
if (auto inheritedConformance = mod->lookupConformance(super, protocol)) {
843855
return ProtocolConformanceRef(ctx.getInheritedConformance(
844856
type, inheritedConformance.getConcrete()));
845857
}
@@ -857,7 +869,7 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
857869
// existential's list of conformances and the existential conforms to
858870
// itself.
859871
if (type->isExistentialType())
860-
return lookupExistentialConformance(type, protocol);
872+
return mod->lookupExistentialConformance(type, protocol);
861873

862874
// Type variables have trivial conformances.
863875
if (type->isTypeVariableOrMember())
@@ -877,7 +889,7 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
877889

878890
// Find the (unspecialized) conformance.
879891
SmallVector<ProtocolConformance *, 2> conformances;
880-
if (!nominal->lookupConformance(this, protocol, conformances))
892+
if (!nominal->lookupConformance(mod, protocol, conformances))
881893
return ProtocolConformanceRef::forInvalid();
882894

883895
// FIXME: Ambiguity resolution.
@@ -897,7 +909,7 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
897909
auto superclassTy = type->getSuperclassForDecl(conformingClass);
898910

899911
// Compute the conformance for the inherited type.
900-
auto inheritedConformance = lookupConformance(superclassTy, protocol);
912+
auto inheritedConformance = mod->lookupConformance(superclassTy, protocol);
901913
assert(inheritedConformance &&
902914
"We already found the inherited conformance");
903915

@@ -918,7 +930,7 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
918930
if (!explicitConformanceType->isEqual(type)) {
919931
// Gather the substitutions we need to map the generic conformance to
920932
// the specialized conformance.
921-
auto subMap = type->getContextSubstitutionMap(this, explicitConformanceDC);
933+
auto subMap = type->getContextSubstitutionMap(mod, explicitConformanceDC);
922934

923935
// Create the specialized conformance entry.
924936
auto result = ctx.getSpecializedConformance(type, conformance, subMap);

lib/AST/NameLookupRequests.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,25 @@ SourceLoc swift::extractNearestSourceLoc(const OperatorLookupDescriptor &desc) {
231231
return desc.diagLoc;
232232
}
233233

234+
//----------------------------------------------------------------------------//
235+
// LookupConformanceInModuleRequest computation.
236+
//----------------------------------------------------------------------------//
237+
238+
void swift::simple_display(llvm::raw_ostream &out,
239+
const LookupConformanceDescriptor &desc) {
240+
out << "looking up conformance to ";
241+
simple_display(out, desc.PD);
242+
out << " for ";
243+
out << desc.Ty.getString();
244+
out << " in ";
245+
simple_display(out, desc.Mod);
246+
}
247+
248+
SourceLoc
249+
swift::extractNearestSourceLoc(const LookupConformanceDescriptor &desc) {
250+
return SourceLoc();
251+
}
252+
234253
// Define request evaluation functions for each of the name lookup requests.
235254
static AbstractRequestFunction *nameLookupRequestFunctions[] = {
236255
#define SWIFT_REQUEST(Zone, Name, Sig, Caching, LocOptions) \

0 commit comments

Comments
 (0)