Skip to content

Commit a4c2ad4

Browse files
committed
RequirementMachine: Use ProtocolDecl::getProtocolDependencies()
When using the requirement machine to build protocol signatures, we can't get the protocol's dependencies by looking at the conformance requirements in it's requirement signature, because we haven't computed the requirement signature yet. Instead, get the dependencies via the recently-added getStructuralRequirements() request.
1 parent f81e4c9 commit a4c2ad4

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

lib/AST/RequirementMachine/ProtocolGraph.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ using namespace rewriting;
2323
void ProtocolGraph::visitRequirements(ArrayRef<Requirement> reqs) {
2424
for (auto req : reqs) {
2525
if (req.getKind() == RequirementKind::Conformance) {
26-
addProtocol(req.getProtocolDecl());
26+
addProtocol(req.getProtocolDecl(), /*initialComponent=*/false);
2727
}
2828
}
2929
}
@@ -32,7 +32,7 @@ void ProtocolGraph::visitRequirements(ArrayRef<Requirement> reqs) {
3232
/// \p protos.
3333
void ProtocolGraph::visitProtocols(ArrayRef<const ProtocolDecl *> protos) {
3434
for (auto proto : protos) {
35-
addProtocol(proto);
35+
addProtocol(proto, /*initialComponent=*/true);
3636
}
3737
}
3838

@@ -50,13 +50,15 @@ const ProtocolInfo &ProtocolGraph::getProtocolInfo(
5050
}
5151

5252
/// Record information about a protocol if we have no seen it yet.
53-
void ProtocolGraph::addProtocol(const ProtocolDecl *proto) {
53+
void ProtocolGraph::addProtocol(const ProtocolDecl *proto,
54+
bool initialComponent) {
5455
if (Info.count(proto) > 0)
5556
return;
5657

5758
Info[proto] = {proto->getInheritedProtocols(),
5859
proto->getAssociatedTypeMembers(),
59-
proto->getRequirementSignature()};
60+
proto->getProtocolDependencies(),
61+
initialComponent};
6062
Protocols.push_back(proto);
6163
}
6264

@@ -66,7 +68,9 @@ void ProtocolGraph::computeTransitiveClosure() {
6668
unsigned i = 0;
6769
while (i < Protocols.size()) {
6870
auto *proto = Protocols[i++];
69-
visitRequirements(getProtocolInfo(proto).Requirements);
71+
for (auto *proto : getProtocolInfo(proto).Dependencies) {
72+
addProtocol(proto, /*initialComponent=*/false);
73+
}
7074
}
7175
}
7276

lib/AST/RequirementMachine/ProtocolGraph.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ struct ProtocolInfo {
4242
/// ProtocolGraph::computeInheritedAssociatedTypes().
4343
llvm::TinyPtrVector<AssociatedTypeDecl *> InheritedAssociatedTypes;
4444

45-
/// The protocol's requirement signature.
46-
ArrayRef<Requirement> Requirements;
45+
/// The protocol's dependencies.
46+
ArrayRef<ProtocolDecl *> Dependencies;
4747

4848
/// Used by ProtocolGraph::computeProtocolDepth() to detect circularity.
4949
unsigned Mark : 1;
@@ -55,27 +55,34 @@ struct ProtocolInfo {
5555

5656
/// Index of the protocol in the linear order. Computed by
5757
/// ProtocolGraph::computeLinearOrder().
58-
unsigned Index : 32;
58+
unsigned Index : 31;
59+
60+
/// When building a protocol requirement signature, the initial set of
61+
/// protocols are marked with this bit.
62+
unsigned InitialComponent : 1;
5963

6064
ProtocolInfo() {
6165
Mark = 0;
6266
Depth = 0;
6367
Index = 0;
68+
InitialComponent = 0;
6469
}
6570

6671
ProtocolInfo(ArrayRef<ProtocolDecl *> inherited,
6772
ArrayRef<AssociatedTypeDecl *> &&types,
68-
ArrayRef<Requirement> reqs)
73+
ArrayRef<ProtocolDecl *> deps,
74+
bool initialComponent)
6975
: Inherited(inherited),
7076
AssociatedTypes(types),
71-
Requirements(reqs) {
77+
Dependencies(deps) {
7278
Mark = 0;
7379
Depth = 0;
7480
Index = 0;
81+
InitialComponent = initialComponent;
7582
}
7683
};
7784

78-
/// Stores cached information about all protocols transtively
85+
/// Stores cached information about all protocols transitively
7986
/// referenced from a set of generic requirements.
8087
///
8188
/// Out-of-line methods are documented in ProtocolGraph.cpp.
@@ -101,7 +108,8 @@ class ProtocolGraph {
101108
const ProtocolDecl *proto) const;
102109

103110
private:
104-
void addProtocol(const ProtocolDecl *proto);
111+
void addProtocol(const ProtocolDecl *proto,
112+
bool initialComponent);
105113
void computeTransitiveClosure();
106114
void computeLinearOrder();
107115
void computeInheritedAssociatedTypes();

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,20 @@ void RewriteSystemBuilder::processProtocolDependencies() {
243243
for (auto *assocType : info.InheritedAssociatedTypes)
244244
addAssociatedType(assocType, proto);
245245

246-
for (auto req : info.Requirements)
247-
addRequirement(req.getCanonical(), proto);
246+
// If this protocol is part of the initial connected component, we're
247+
// building requirement signatures for all protocols in this component,
248+
// and so we must start with the structural requirements.
249+
//
250+
// Otherwise, we should either already have a requirement signature, or
251+
// we can trigger the computation of the requirement signatures of the
252+
// next component recursively.
253+
if (info.InitialComponent) {
254+
for (auto req : proto->getStructuralRequirements())
255+
addRequirement(req.req.getCanonical(), proto);
256+
} else {
257+
for (auto req : proto->getRequirementSignature())
258+
addRequirement(req.getCanonical(), proto);
259+
}
248260

249261
if (Dump) {
250262
llvm::dbgs() << "}\n";

lib/Sema/TypeCheckDecl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,12 @@ ProtocolDependenciesRequest::evaluate(Evaluator &evaluator,
10931093

10941094
// If we have a serialized requirement signature, deserialize it and
10951095
// look at conformance requirements.
1096-
if (proto->hasLazyRequirementSignature()) {
1096+
//
1097+
// FIXME: For now we just fall back to the GSB for all protocols
1098+
// unless -requirement-machine-protocol-signatures=on is passed.
1099+
if (proto->hasLazyRequirementSignature() ||
1100+
(ctx.LangOpts.RequirementMachineProtocolSignatures
1101+
== RequirementMachineMode::Disabled)) {
10971102
for (auto req : proto->getRequirementSignature()) {
10981103
if (req.getKind() == RequirementKind::Conformance) {
10991104
result.push_back(req.getProtocolDecl());

0 commit comments

Comments
 (0)