Skip to content

Commit 82f34b9

Browse files
committed
[AST] NameLookup: Add a request to gather protocol requirements
1 parent dd69e11 commit 82f34b9

File tree

7 files changed

+86
-30
lines changed

7 files changed

+86
-30
lines changed

include/swift/AST/Decl.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
532532
IsComputingSemanticMembers : 1
533533
);
534534

535-
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+8,
535+
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+8,
536536
/// Whether the \c RequiresClass bit is valid.
537537
RequiresClassValid : 1,
538538

@@ -570,6 +570,9 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
570570
/// Whether we have a lazy-loaded list of primary associated types.
571571
HasLazyPrimaryAssociatedTypes : 1,
572572

573+
/// Whether we've computed the protocol requirements list yet.
574+
ProtocolRequirementsValid : 1,
575+
573576
: NumPadBits,
574577

575578
/// If this is a compiler-known protocol, this will be a KnownProtocolKind
@@ -4579,6 +4582,7 @@ class ProtocolDecl final : public NominalTypeDecl {
45794582
ArrayRef<PrimaryAssociatedTypeName> PrimaryAssociatedTypeNames;
45804583
ArrayRef<ProtocolDecl *> InheritedProtocols;
45814584
ArrayRef<AssociatedTypeDecl *> AssociatedTypes;
4585+
ArrayRef<ValueDecl *> ProtocolRequirements;
45824586

45834587
struct {
45844588
/// The superclass decl and a bit to indicate whether the
@@ -4660,6 +4664,7 @@ class ProtocolDecl final : public NominalTypeDecl {
46604664
friend class ExistentialRequiresAnyRequest;
46614665
friend class InheritedProtocolsRequest;
46624666
friend class PrimaryAssociatedTypesRequest;
4667+
friend class ProtocolRequirementsRequest;
46634668

46644669
public:
46654670
ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
@@ -4703,6 +4708,10 @@ class ProtocolDecl final : public NominalTypeDecl {
47034708
/// parametrized protocol type of the form SomeProtocol<Arg1, Arg2...>.
47044709
ArrayRef<AssociatedTypeDecl *> getPrimaryAssociatedTypes() const;
47054710

4711+
/// Returns the list of all requirements (associated type and value)
4712+
/// associated with this protocol.
4713+
ArrayRef<ValueDecl *> getProtocolRequirements() const;
4714+
47064715
/// Returns a protocol requirement with the given name, or nullptr if the
47074716
/// name has multiple overloads, or no overloads at all.
47084717
ValueDecl *getSingleRequirement(DeclName name) const;
@@ -4776,6 +4785,13 @@ class ProtocolDecl final : public NominalTypeDecl {
47764785
Bits.ProtocolDecl.InheritedProtocolsValid = true;
47774786
}
47784787

4788+
bool areProtocolRequirementsValid() const {
4789+
return Bits.ProtocolDecl.ProtocolRequirementsValid;
4790+
}
4791+
void setProtocolRequirementsValid() {
4792+
Bits.ProtocolDecl.ProtocolRequirementsValid = true;
4793+
}
4794+
47794795
public:
47804796
/// If this is known to be a compiler-known protocol, returns the kind.
47814797
/// Otherwise returns None.

include/swift/AST/NameLookupRequests.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,26 @@ class InheritedProtocolsRequest
196196
ArrayRef<ProtocolDecl *> result) const;
197197
};
198198

199+
class ProtocolRequirementsRequest
200+
: public SimpleRequest<ProtocolRequirementsRequest,
201+
ArrayRef<ValueDecl *>(ProtocolDecl *),
202+
RequestFlags::SeparatelyCached> {
203+
public:
204+
using SimpleRequest::SimpleRequest;
205+
206+
private:
207+
friend SimpleRequest;
208+
209+
// Evaluation.
210+
ArrayRef<ValueDecl *> evaluate(Evaluator &, ProtocolDecl *) const;
211+
212+
public:
213+
// Caching
214+
bool isCached() const { return true; }
215+
Optional<ArrayRef<ValueDecl *>> getCachedResult() const;
216+
void cacheResult(ArrayRef<ValueDecl *> value) const;
217+
};
218+
199219
/// Requests whether or not this class has designated initializers that are
200220
/// not public or @usableFromInline.
201221
class HasMissingDesignatedInitializersRequest :

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
SWIFT_REQUEST(NameLookup, InheritedProtocolsRequest,
4848
ArrayRef<ProtocolDecl *>(ProtocolDecl *), SeparatelyCached,
4949
NoLocationInfo)
50+
SWIFT_REQUEST(NameLookup, ProtocolRequirementsRequest,
51+
ArrayRef<ValueDecl *>(ProtocolDecl *), SeparatelyCached,
52+
NoLocationInfo)
5053
SWIFT_REQUEST(NameLookup, LookupConformanceInModuleRequest,
5154
ProtocolConformanceRef(LookupConformanceDescriptor),
5255
Uncached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5494,6 +5494,7 @@ ProtocolDecl::ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc,
54945494
Bits.ProtocolDecl.KnownProtocol = 0;
54955495
Bits.ProtocolDecl.HasAssociatedTypes = 0;
54965496
Bits.ProtocolDecl.HasLazyAssociatedTypes = 0;
5497+
Bits.ProtocolDecl.ProtocolRequirementsValid = false;
54975498
setTrailingWhereClause(TrailingWhere);
54985499
}
54995500

@@ -5533,7 +5534,7 @@ ProtocolDecl::getAssociatedTypeMembers() const {
55335534
contextData->loader->loadAssociatedTypes(
55345535
this, contextData->associatedTypesData, result);
55355536
} else {
5536-
for (auto member : getABIMembers()) {
5537+
for (auto member : getProtocolRequirements()) {
55375538
if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
55385539
result.push_back(ATD);
55395540
}
@@ -5544,6 +5545,12 @@ ProtocolDecl::getAssociatedTypeMembers() const {
55445545
return AssociatedTypes;
55455546
}
55465547

5548+
ArrayRef<ValueDecl *> ProtocolDecl::getProtocolRequirements() const {
5549+
auto *mutableSelf = const_cast<ProtocolDecl *>(this);
5550+
return evaluateOrDefault(getASTContext().evaluator,
5551+
ProtocolRequirementsRequest{mutableSelf}, {});
5552+
}
5553+
55475554
ValueDecl *ProtocolDecl::getSingleRequirement(DeclName name) const {
55485555
auto results = const_cast<ProtocolDecl *>(this)->lookupDirect(name);
55495556
ValueDecl *result = nullptr;

lib/AST/NameLookup.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,6 +2723,20 @@ InheritedProtocolsRequest::evaluate(Evaluator &evaluator,
27232723
return PD->getASTContext().AllocateCopy(result);
27242724
}
27252725

2726+
ArrayRef<ValueDecl *>
2727+
ProtocolRequirementsRequest::evaluate(Evaluator &evaluator,
2728+
ProtocolDecl *PD) const {
2729+
SmallVector<ValueDecl *, 4> requirements;
2730+
2731+
for (auto *member : PD->getABIMembers()) {
2732+
auto *VD = dyn_cast<ValueDecl>(member);
2733+
if (VD && VD->isProtocolRequirement())
2734+
requirements.push_back(VD);
2735+
}
2736+
2737+
return PD->getASTContext().AllocateCopy(requirements);
2738+
}
2739+
27262740
NominalTypeDecl *
27272741
ExtendedNominalRequest::evaluate(Evaluator &evaluator,
27282742
ExtensionDecl *ext) const {

lib/AST/NameLookupRequests.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,21 @@ void InheritedProtocolsRequest::writeDependencySink(
111111
}
112112
}
113113

114+
Optional<ArrayRef<ValueDecl *>>
115+
ProtocolRequirementsRequest::getCachedResult() const {
116+
auto proto = std::get<0>(getStorage());
117+
if (!proto->areProtocolRequirementsValid())
118+
return None;
119+
120+
return proto->ProtocolRequirements;
121+
}
122+
123+
void ProtocolRequirementsRequest::cacheResult(ArrayRef<ValueDecl *> PDs) const {
124+
auto proto = std::get<0>(getStorage());
125+
proto->ProtocolRequirements = PDs;
126+
proto->setProtocolRequirementsValid();
127+
}
128+
114129
//----------------------------------------------------------------------------//
115130
// Missing designated initializers computation
116131
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,10 +1817,7 @@ void MultiConformanceChecker::checkAllConformances() {
18171817
return *checker;
18181818
};
18191819

1820-
for (auto member : proto->getABIMembers()) {
1821-
auto req = dyn_cast<ValueDecl>(member);
1822-
if (!req || !req->isProtocolRequirement()) continue;
1823-
1820+
for (auto *req : proto->getProtocolRequirements()) {
18241821
// If the requirement is unsatisfied, we might want to warn
18251822
// about near misses; record it.
18261823
if (isUnsatisfiedReq(getChecker(), conformance, req)) {
@@ -5124,19 +5121,11 @@ hasInvalidTypeInConformanceContext(const ValueDecl *requirement,
51245121
}
51255122

51265123
void ConformanceChecker::resolveValueWitnesses() {
5127-
for (auto member : Proto->getABIMembers()) {
5128-
auto requirement = dyn_cast<ValueDecl>(member);
5129-
if (!requirement)
5130-
continue;
5131-
5124+
for (auto *requirement : Proto->getProtocolRequirements()) {
51325125
// Associated type requirements handled elsewhere.
51335126
if (isa<TypeDecl>(requirement))
51345127
continue;
51355128

5136-
// Type aliases don't have requirements themselves.
5137-
if (!requirement->isProtocolRequirement())
5138-
continue;
5139-
51405129
/// Local function to finalize the witness.
51415130
auto finalizeWitness = [&] {
51425131
// Find the witness.
@@ -5467,7 +5456,7 @@ ConformanceChecker::getObjCRequirements(ObjCMethodKey key) {
54675456

54685457
// Fill in the data structure if we haven't done so yet.
54695458
if (!computedObjCMethodRequirements) {
5470-
for (auto requirement : proto->getABIMembers()) {
5459+
for (auto requirement : proto->getProtocolRequirements()) {
54715460
auto funcRequirement = dyn_cast<AbstractFunctionDecl>(requirement);
54725461
if (!funcRequirement)
54735462
continue;
@@ -7129,15 +7118,11 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
71297118
return {defaultType, defaultedAssocType};
71307119
};
71317120

7132-
for (auto *requirement : proto->getABIMembers()) {
7121+
for (auto *requirement : proto->getProtocolRequirements()) {
71337122
if (requirement->isInvalid())
71347123
continue;
71357124

7136-
auto *valueDecl = dyn_cast<ValueDecl>(requirement);
7137-
if (!valueDecl)
7138-
continue;
7139-
7140-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(valueDecl)) {
7125+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(requirement)) {
71417126
if (assocType->getOverriddenDecls().empty()) {
71427127
if (Type defaultType = findAssociatedTypeDefault(assocType).first)
71437128
proto->setDefaultTypeWitness(assocType, defaultType);
@@ -7146,20 +7131,16 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
71467131
continue;
71477132
}
71487133

7149-
if (isa<TypeDecl>(valueDecl))
7150-
continue;
7151-
7152-
if (!valueDecl->isProtocolRequirement())
7153-
continue;
7134+
assert(!isa<TypeDecl>(requirement));
71547135

7155-
ResolveWitnessResult result = checker.resolveWitnessViaLookup(valueDecl);
7136+
ResolveWitnessResult result = checker.resolveWitnessViaLookup(requirement);
71567137

71577138
if (result == ResolveWitnessResult::Missing &&
71587139
requirement->isSPI() &&
71597140
!proto->isSPI()) {
71607141
// SPI requirements need a default value, unless the protocol is SPI too.
7161-
valueDecl->diagnose(diag::spi_attribute_on_protocol_requirement,
7162-
valueDecl->getName());
7142+
requirement->diagnose(diag::spi_attribute_on_protocol_requirement,
7143+
requirement->getName());
71637144
}
71647145
}
71657146

0 commit comments

Comments
 (0)