Skip to content

Commit 0aa036a

Browse files
authored
Merge pull request #61915 from xedin/switch-protocol-checking-to-abi-members
[AST/Sema] Switch protocol requirement inference to use `getABIMembers()`
2 parents 31ab259 + 82f34b9 commit 0aa036a

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
@@ -5490,6 +5490,7 @@ ProtocolDecl::ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc,
54905490
Bits.ProtocolDecl.KnownProtocol = 0;
54915491
Bits.ProtocolDecl.HasAssociatedTypes = 0;
54925492
Bits.ProtocolDecl.HasLazyAssociatedTypes = 0;
5493+
Bits.ProtocolDecl.ProtocolRequirementsValid = false;
54935494
setTrailingWhereClause(TrailingWhere);
54945495
}
54955496

@@ -5529,7 +5530,7 @@ ProtocolDecl::getAssociatedTypeMembers() const {
55295530
contextData->loader->loadAssociatedTypes(
55305531
this, contextData->associatedTypesData, result);
55315532
} else {
5532-
for (auto member : getMembers()) {
5533+
for (auto member : getProtocolRequirements()) {
55335534
if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
55345535
result.push_back(ATD);
55355536
}
@@ -5540,6 +5541,12 @@ ProtocolDecl::getAssociatedTypeMembers() const {
55405541
return AssociatedTypes;
55415542
}
55425543

5544+
ArrayRef<ValueDecl *> ProtocolDecl::getProtocolRequirements() const {
5545+
auto *mutableSelf = const_cast<ProtocolDecl *>(this);
5546+
return evaluateOrDefault(getASTContext().evaluator,
5547+
ProtocolRequirementsRequest{mutableSelf}, {});
5548+
}
5549+
55435550
ValueDecl *ProtocolDecl::getSingleRequirement(DeclName name) const {
55445551
auto results = const_cast<ProtocolDecl *>(this)->lookupDirect(name);
55455552
ValueDecl *result = nullptr;

lib/AST/NameLookup.cpp

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

2721+
ArrayRef<ValueDecl *>
2722+
ProtocolRequirementsRequest::evaluate(Evaluator &evaluator,
2723+
ProtocolDecl *PD) const {
2724+
SmallVector<ValueDecl *, 4> requirements;
2725+
2726+
for (auto *member : PD->getABIMembers()) {
2727+
auto *VD = dyn_cast<ValueDecl>(member);
2728+
if (VD && VD->isProtocolRequirement())
2729+
requirements.push_back(VD);
2730+
}
2731+
2732+
return PD->getASTContext().AllocateCopy(requirements);
2733+
}
2734+
27212735
NominalTypeDecl *
27222736
ExtendedNominalRequest::evaluate(Evaluator &evaluator,
27232737
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->getMembers()) {
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)) {
@@ -5117,19 +5114,11 @@ hasInvalidTypeInConformanceContext(const ValueDecl *requirement,
51175114
}
51185115

51195116
void ConformanceChecker::resolveValueWitnesses() {
5120-
for (auto member : Proto->getMembers()) {
5121-
auto requirement = dyn_cast<ValueDecl>(member);
5122-
if (!requirement)
5123-
continue;
5124-
5117+
for (auto *requirement : Proto->getProtocolRequirements()) {
51255118
// Associated type requirements handled elsewhere.
51265119
if (isa<TypeDecl>(requirement))
51275120
continue;
51285121

5129-
// Type aliases don't have requirements themselves.
5130-
if (!requirement->isProtocolRequirement())
5131-
continue;
5132-
51335122
/// Local function to finalize the witness.
51345123
auto finalizeWitness = [&] {
51355124
// Find the witness.
@@ -5434,7 +5423,7 @@ ConformanceChecker::getObjCRequirements(ObjCMethodKey key) {
54345423

54355424
// Fill in the data structure if we haven't done so yet.
54365425
if (!computedObjCMethodRequirements) {
5437-
for (auto requirement : proto->getABIMembers()) {
5426+
for (auto requirement : proto->getProtocolRequirements()) {
54385427
auto funcRequirement = dyn_cast<AbstractFunctionDecl>(requirement);
54395428
if (!funcRequirement)
54405429
continue;
@@ -7096,15 +7085,11 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
70967085
return {defaultType, defaultedAssocType};
70977086
};
70987087

7099-
for (auto *requirement : proto->getMembers()) {
7088+
for (auto *requirement : proto->getProtocolRequirements()) {
71007089
if (requirement->isInvalid())
71017090
continue;
71027091

7103-
auto *valueDecl = dyn_cast<ValueDecl>(requirement);
7104-
if (!valueDecl)
7105-
continue;
7106-
7107-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(valueDecl)) {
7092+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(requirement)) {
71087093
if (assocType->getOverriddenDecls().empty()) {
71097094
if (Type defaultType = findAssociatedTypeDefault(assocType).first)
71107095
proto->setDefaultTypeWitness(assocType, defaultType);
@@ -7113,20 +7098,16 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
71137098
continue;
71147099
}
71157100

7116-
if (isa<TypeDecl>(valueDecl))
7117-
continue;
7118-
7119-
if (!valueDecl->isProtocolRequirement())
7120-
continue;
7101+
assert(!isa<TypeDecl>(requirement));
71217102

7122-
ResolveWitnessResult result = checker.resolveWitnessViaLookup(valueDecl);
7103+
ResolveWitnessResult result = checker.resolveWitnessViaLookup(requirement);
71237104

71247105
if (result == ResolveWitnessResult::Missing &&
71257106
requirement->isSPI() &&
71267107
!proto->isSPI()) {
71277108
// SPI requirements need a default value, unless the protocol is SPI too.
7128-
valueDecl->diagnose(diag::spi_attribute_on_protocol_requirement,
7129-
valueDecl->getName());
7109+
requirement->diagnose(diag::spi_attribute_on_protocol_requirement,
7110+
requirement->getName());
71307111
}
71317112
}
71327113

0 commit comments

Comments
 (0)