Skip to content

Commit 5249432

Browse files
committed
Sema: Don't need to pass the ConformanceChecker around so much
I want to slim down ConformanceChecker because it doesn't really fit with request-driven resolution of witnesses. This is a first step towards that.
1 parent 09087cc commit 5249432

File tree

5 files changed

+73
-59
lines changed

5 files changed

+73
-59
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,6 +2829,25 @@ class TypeWitnessRequest
28292829
void cacheResult(TypeWitnessAndDecl value) const;
28302830
};
28312831

2832+
class ReferencedAssociatedTypesRequest
2833+
: public SimpleRequest<ReferencedAssociatedTypesRequest,
2834+
TinyPtrVector<AssociatedTypeDecl *>(ValueDecl *),
2835+
RequestFlags::Cached> {
2836+
public:
2837+
using SimpleRequest::SimpleRequest;
2838+
2839+
private:
2840+
friend SimpleRequest;
2841+
2842+
// Evaluation.
2843+
TinyPtrVector<AssociatedTypeDecl *>
2844+
evaluate(Evaluator &evaluator, ValueDecl *req) const;
2845+
2846+
public:
2847+
// Caching.
2848+
bool isCached() const { return true; }
2849+
};
2850+
28322851
class ValueWitnessRequest
28332852
: public SimpleRequest<ValueWitnessRequest,
28342853
Witness(NormalProtocolConformance *, ValueDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ SWIFT_REQUEST(TypeChecker, AssociatedConformanceRequest,
426426
ProtocolConformanceRef(NormalProtocolConformance *,
427427
Type, ProtocolDecl *, unsigned),
428428
SeparatelyCached, NoLocationInfo)
429+
SWIFT_REQUEST(TypeChecker, ReferencedAssociatedTypesRequest,
430+
TinyPtrVector<AssociatedTypeDecl *>(ValueDecl *),
431+
Cached, NoLocationInfo)
429432
SWIFT_REQUEST(TypeChecker, ValueWitnessRequest,
430433
Witness(NormalProtocolConformance *, ValueDecl *),
431434
SeparatelyCached, NoLocationInfo)

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,9 @@ WitnessChecker::WitnessChecker(ASTContext &ctx, ProtocolDecl *proto,
13591359
Type adoptee, DeclContext *dc)
13601360
: Context(ctx), Proto(proto), Adoptee(adoptee), DC(dc) {}
13611361

1362-
void
1363-
WitnessChecker::lookupValueWitnessesViaImplementsAttr(
1364-
ValueDecl *req, SmallVector<ValueDecl *, 4> &witnesses) {
1362+
static void
1363+
lookupValueWitnessesViaImplementsAttr(
1364+
DeclContext *DC, ValueDecl *req, SmallVector<ValueDecl *, 4> &witnesses) {
13651365

13661366
auto name = req->createNameRef();
13671367
auto *nominal = DC->getSelfNominalTypeDecl();
@@ -1411,15 +1411,15 @@ static bool contextMayExpandOperator(
14111411
}
14121412

14131413
SmallVector<ValueDecl *, 4>
1414-
WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) {
1414+
swift::lookupValueWitnesses(DeclContext *DC, ValueDecl *req, bool *ignoringNames) {
14151415
assert(!isa<AssociatedTypeDecl>(req) && "Not for lookup for type witnesses*");
14161416
assert(req->isProtocolRequirement());
14171417

14181418
SmallVector<ValueDecl *, 4> witnesses;
14191419

14201420
// Do an initial check to see if there are any @_implements remappings
14211421
// for this requirement.
1422-
lookupValueWitnessesViaImplementsAttr(req, witnesses);
1422+
lookupValueWitnessesViaImplementsAttr(DC, req, witnesses);
14231423

14241424
auto reqName = req->createNameRef();
14251425
auto reqBaseName = reqName.withoutArgumentLabels();
@@ -1441,7 +1441,7 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) {
14411441
for (auto candidate : lookup) {
14421442
auto decl = candidate.getValueDecl();
14431443
if (!isa<ProtocolDecl>(decl->getDeclContext()) &&
1444-
swift::isMemberOperator(cast<FuncDecl>(decl), Adoptee)) {
1444+
swift::isMemberOperator(cast<FuncDecl>(decl), DC->getSelfInterfaceType())) {
14451445
witnesses.push_back(decl);
14461446
}
14471447
}
@@ -1515,7 +1515,7 @@ bool WitnessChecker::findBestWitness(
15151515
SmallVector<ValueDecl *, 4> witnesses;
15161516
switch (attempt) {
15171517
case Regular:
1518-
witnesses = lookupValueWitnesses(requirement, ignoringNames);
1518+
witnesses = lookupValueWitnesses(DC, requirement, ignoringNames);
15191519
break;
15201520
case OperatorsFromOverlay: {
15211521
// If we have a Clang declaration, the matching operator might be in the
@@ -2924,29 +2924,26 @@ ConformanceChecker::~ConformanceChecker() {
29242924
!getASTContext().hasDelayedConformanceErrors(Conformance));
29252925
}
29262926

2927-
ArrayRef<AssociatedTypeDecl *>
2928-
ConformanceChecker::getReferencedAssociatedTypes(ValueDecl *req) {
2929-
// Check whether we've already cached this information.
2930-
auto known = ReferencedAssociatedTypes.find(req);
2931-
if (known != ReferencedAssociatedTypes.end())
2932-
return known->second;
29332927

2928+
TinyPtrVector<AssociatedTypeDecl *>
2929+
ReferencedAssociatedTypesRequest::evaluate(Evaluator &eval,
2930+
ValueDecl *req) const {
29342931
// Collect the set of associated types rooted on Self in the
29352932
// signature. Note that for references to nested types, we only
29362933
// want to consider the outermost dependent member type.
29372934
//
29382935
// For example, a requirement typed '(Iterator.Element) -> ()'
29392936
// is not considered to reference the associated type 'Iterator'.
2940-
auto &assocTypes = ReferencedAssociatedTypes[req];
2937+
TinyPtrVector<AssociatedTypeDecl *> assocTypes;
29412938

29422939
class Walker : public TypeWalker {
29432940
ProtocolDecl *Proto;
2944-
llvm::SmallVectorImpl<AssociatedTypeDecl *> &assocTypes;
2941+
llvm::TinyPtrVector<AssociatedTypeDecl *> &assocTypes;
29452942
llvm::SmallPtrSet<AssociatedTypeDecl *, 4> knownAssocTypes;
29462943

29472944
public:
29482945
Walker(ProtocolDecl *Proto,
2949-
llvm::SmallVectorImpl<AssociatedTypeDecl *> &assocTypes)
2946+
llvm::TinyPtrVector<AssociatedTypeDecl *> &assocTypes)
29502947
: Proto(Proto), assocTypes(assocTypes) {}
29512948

29522949
Action walkToTypePre(Type type) override {
@@ -2963,7 +2960,7 @@ ConformanceChecker::getReferencedAssociatedTypes(ValueDecl *req) {
29632960
}
29642961
};
29652962

2966-
Walker walker(Proto, assocTypes);
2963+
Walker walker(cast<ProtocolDecl>(req->getDeclContext()), assocTypes);
29672964

29682965
// This dance below is to avoid calling getCanonicalType() on a
29692966
// GenericFunctionType, which creates a GenericSignatureBuilder, which
@@ -4301,7 +4298,10 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
43014298

43024299
// If any of the type witnesses was erroneous, don't bother to check
43034300
// this value witness: it will fail.
4304-
for (auto assocType : getReferencedAssociatedTypes(requirement)) {
4301+
auto referenced = evaluateOrDefault(getASTContext().evaluator,
4302+
ReferencedAssociatedTypesRequest{requirement},
4303+
TinyPtrVector<AssociatedTypeDecl *>());
4304+
for (auto assocType : referenced) {
43054305
if (Conformance->getTypeWitness(assocType)->hasError()) {
43064306
return ResolveWitnessResult::ExplicitFailed;
43074307
}

lib/Sema/TypeCheckProtocol.h

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,19 @@ struct RequirementMatch {
636636
swift::Witness getWitness(ASTContext &ctx) const;
637637
};
638638

639+
/// Gather the value witnesses for the given requirement.
640+
///
641+
/// \param DC A nominal type or extension context where the conformance
642+
/// was declared.
643+
/// \param req A member of a protocol that DC conforms to.
644+
/// \param ignoringNames If non-null and there are no value
645+
/// witnesses with the correct full name, the results will reflect
646+
/// lookup for just the base name and the pointee will be set to
647+
/// \c true.
648+
SmallVector<ValueDecl *, 4> lookupValueWitnesses(DeclContext *DC,
649+
ValueDecl *req,
650+
bool *ignoringNames);
651+
639652
struct RequirementCheck;
640653

641654
class WitnessChecker {
@@ -676,15 +689,6 @@ class WitnessChecker {
676689
return RequiredAccessScopeAndUsableFromInline.value().second;
677690
}
678691

679-
/// Gather the value witnesses for the given requirement.
680-
///
681-
/// \param ignoringNames If non-null and there are no value
682-
/// witnesses with the correct full name, the results will reflect
683-
/// lookup for just the base name and the pointee will be set to
684-
/// \c true.
685-
SmallVector<ValueDecl *, 4> lookupValueWitnesses(ValueDecl *req,
686-
bool *ignoringNames);
687-
688692
void lookupValueWitnessesViaImplementsAttr(ValueDecl *req,
689693
SmallVector<ValueDecl *, 4>
690694
&witnesses);
@@ -774,11 +778,6 @@ class ConformanceChecker : public WitnessChecker {
774778
/// Witnesses that are currently being resolved.
775779
llvm::SmallPtrSet<ValueDecl *, 4> ResolvingWitnesses;
776780

777-
/// Caches the set of associated types that are referenced in each
778-
/// requirement.
779-
llvm::DenseMap<ValueDecl *, llvm::SmallVector<AssociatedTypeDecl *, 2>>
780-
ReferencedAssociatedTypes;
781-
782781
/// Keep track of missing witnesses, either type or value, for later
783782
/// diagnosis emits. This may contain witnesses that are external to the
784783
/// protocol under checking.
@@ -804,10 +803,6 @@ class ConformanceChecker : public WitnessChecker {
804803
/// Whether objcMethodRequirements has been computed.
805804
bool computedObjCMethodRequirements = false;
806805

807-
/// Retrieve the associated types that are referenced by the given
808-
/// requirement with a base of 'Self'.
809-
ArrayRef<AssociatedTypeDecl *> getReferencedAssociatedTypes(ValueDecl *req);
810-
811806
/// Record a (non-type) witness for the given requirement.
812807
void recordWitness(ValueDecl *requirement, const RequirementMatch &match);
813808

@@ -1132,13 +1127,11 @@ class AssociatedTypeInference {
11321127

11331128
/// Infer associated type witnesses for the given value requirement.
11341129
InferredAssociatedTypesByWitnesses inferTypeWitnessesViaValueWitnesses(
1135-
ConformanceChecker &checker,
11361130
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
11371131
ValueDecl *req);
11381132

11391133
/// Infer associated type witnesses for the given associated type.
11401134
InferredAssociatedTypesByWitnesses inferTypeWitnessesViaAssociatedType(
1141-
ConformanceChecker &checker,
11421135
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
11431136
AssociatedTypeDecl *assocType);
11441137

@@ -1147,7 +1140,6 @@ class AssociatedTypeInference {
11471140
/// \param assocTypes The set of associated types we're interested in.
11481141
InferredAssociatedTypes
11491142
inferTypeWitnessesViaValueWitnesses(
1150-
ConformanceChecker &checker,
11511143
const llvm::SetVector<AssociatedTypeDecl *> &assocTypes);
11521144

11531145
/// Compute a "fixed" type witness for an associated type, e.g.,
@@ -1255,8 +1247,7 @@ class AssociatedTypeInference {
12551247
/// involving multiple files/modules, and not in tests within the Swift
12561248
/// project itself.
12571249
bool canAttemptEagerTypeWitnessDerivation(
1258-
ConformanceChecker &checker,
1259-
AssociatedTypeDecl *assocType);
1250+
DeclContext *DC, AssociatedTypeDecl *assocType);
12601251

12611252
public:
12621253
/// Describes a mapping from associated type declarations to their

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/SubstitutionMap.h"
2626
#include "swift/AST/TypeMatcher.h"
2727
#include "swift/AST/Types.h"
28+
#include "swift/AST/TypeCheckRequests.h"
2829
#include "swift/Basic/Defer.h"
2930
#include "swift/ClangImporter/ClangModule.h"
3031
#include "llvm/ADT/Statistic.h"
@@ -374,7 +375,6 @@ static bool isExtensionUsableForInference(const ExtensionDecl *extension,
374375

375376
InferredAssociatedTypesByWitnesses
376377
AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
377-
ConformanceChecker &checker,
378378
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
379379
ValueDecl *req) {
380380
// Conformances constructed by the ClangImporter should have explicit type
@@ -392,7 +392,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
392392
InferredAssociatedTypesByWitnesses result;
393393

394394
for (auto witness :
395-
checker.lookupValueWitnesses(req, /*ignoringNames=*/nullptr)) {
395+
lookupValueWitnesses(dc, req, /*ignoringNames=*/nullptr)) {
396396
LLVM_DEBUG(llvm::dbgs() << "Inferring associated types from decl:\n";
397397
witness->dump(llvm::dbgs()));
398398

@@ -582,9 +582,7 @@ next_witness:;
582582

583583
InferredAssociatedTypes
584584
AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
585-
ConformanceChecker &checker,
586-
const llvm::SetVector<AssociatedTypeDecl *> &assocTypes)
587-
{
585+
const llvm::SetVector<AssociatedTypeDecl *> &assocTypes) {
588586
InferredAssociatedTypes result;
589587
for (auto member : proto->getMembers()) {
590588
auto req = dyn_cast<ValueDecl>(member);
@@ -598,8 +596,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
598596
if (assocTypes.count(assocType) == 0)
599597
continue;
600598

601-
auto reqInferred = inferTypeWitnessesViaAssociatedType(checker,
602-
assocTypes,
599+
auto reqInferred = inferTypeWitnessesViaAssociatedType(assocTypes,
603600
assocType);
604601
if (!reqInferred.empty())
605602
result.push_back({req, std::move(reqInferred)});
@@ -623,7 +620,9 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
623620
// Check whether any of the associated types we care about are
624621
// referenced in this value requirement.
625622
{
626-
const auto referenced = checker.getReferencedAssociatedTypes(req);
623+
auto referenced = evaluateOrDefault(ctx.evaluator,
624+
ReferencedAssociatedTypesRequest{req},
625+
TinyPtrVector<AssociatedTypeDecl *>());
627626
if (llvm::find_if(referenced, [&](AssociatedTypeDecl *const assocType) {
628627
return assocTypes.count(assocType);
629628
}) == referenced.end())
@@ -633,7 +632,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
633632
// Infer associated types from the potential value witnesses for
634633
// this requirement.
635634
auto reqInferred =
636-
inferTypeWitnessesViaValueWitnesses(checker, assocTypes, req);
635+
inferTypeWitnessesViaValueWitnesses(assocTypes, req);
637636
if (reqInferred.empty())
638637
continue;
639638

@@ -738,7 +737,6 @@ static Type removeSelfParam(ValueDecl *value, Type type) {
738737

739738
InferredAssociatedTypesByWitnesses
740739
AssociatedTypeInference::inferTypeWitnessesViaAssociatedType(
741-
ConformanceChecker &checker,
742740
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
743741
AssociatedTypeDecl *assocType) {
744742
// Form the default name _Default_Foo.
@@ -2513,13 +2511,13 @@ bool AssociatedTypeInference::diagnoseAmbiguousSolutions(
25132511
}
25142512

25152513
bool AssociatedTypeInference::canAttemptEagerTypeWitnessDerivation(
2516-
ConformanceChecker &checker,
2517-
AssociatedTypeDecl *assocType) {
2514+
DeclContext *DC, AssociatedTypeDecl *assocType) {
25182515

25192516
/// Rather than locating the TypeID via the default implementation of
25202517
/// Identifiable, we need to find the type based on the associated ActorSystem
2521-
if (checker.Adoptee->isDistributedActor() &&
2522-
assocType->getProtocol()->isSpecificProtocol(KnownProtocolKind::Identifiable)) {
2518+
if (auto *nominal = DC->getSelfNominalTypeDecl())
2519+
if (nominal->isDistributedActor() &&
2520+
assocType->getProtocol()->isSpecificProtocol(KnownProtocolKind::Identifiable)) {
25232521
return true;
25242522
}
25252523

@@ -2550,7 +2548,7 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
25502548
if (conformance->hasTypeWitness(assocType))
25512549
continue;
25522550

2553-
if (canAttemptEagerTypeWitnessDerivation(checker, assocType)) {
2551+
if (canAttemptEagerTypeWitnessDerivation(dc, assocType)) {
25542552
auto derivedType = computeDerivedTypeWitness(assocType);
25552553
if (derivedType.first) {
25562554
checker.recordTypeWitness(assocType,
@@ -2602,8 +2600,7 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
26022600
return result;
26032601

26042602
// Infer potential type witnesses from value witnesses.
2605-
inferred = inferTypeWitnessesViaValueWitnesses(checker,
2606-
unresolvedAssocTypes);
2603+
inferred = inferTypeWitnessesViaValueWitnesses(unresolvedAssocTypes);
26072604
LLVM_DEBUG(llvm::dbgs() << "Candidates for inference:\n";
26082605
dumpInferredAssociatedTypes(inferred));
26092606

@@ -3036,7 +3033,11 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
30363033

30373034
// If any of the type witnesses was erroneous, don't bother to check
30383035
// this value witness: it will fail.
3039-
for (auto assocType : getReferencedAssociatedTypes(requirement)) {
3036+
auto assocTypes = evaluateOrDefault(getASTContext().evaluator,
3037+
ReferencedAssociatedTypesRequest{requirement},
3038+
TinyPtrVector<AssociatedTypeDecl *>());
3039+
3040+
for (auto assocType : assocTypes) {
30403041
if (Conformance->getTypeWitness(assocType)->hasError()) {
30413042
Conformance->setInvalid();
30423043
return;

0 commit comments

Comments
 (0)