@@ -32,7 +32,23 @@ struct RewriteSystemBuilder {
3232 RewriteContext &Context;
3333 bool Dump;
3434
35- ProtocolGraph Protocols;
35+ // / The keys are the unique protocols we've added so far. The value indicates
36+ // / whether the protocol's SCC is an initial component for the rewrite system.
37+ // /
38+ // / A rewrite system built from a generic signature does not have any initial
39+ // / protocols.
40+ // /
41+ // / A rewrite system built from a protocol SCC has the protocols of the SCC
42+ // / itself as initial protocols.
43+ // /
44+ // / If a protocol is an initial protocol, we use its structural requirements
45+ // / instead of its requirement signature as the basis of its rewrite rules.
46+ // /
47+ // / This is what breaks the cycle in requirement signature computation for a
48+ // / group of interdependent protocols.
49+ llvm::DenseMap<const ProtocolDecl *, bool > ProtocolMap;
50+ std::vector<const ProtocolDecl *> Protocols;
51+
3652 std::vector<std::pair<MutableTerm, MutableTerm>> AssociatedTypeRules;
3753 std::vector<std::pair<MutableTerm, MutableTerm>> RequirementRules;
3854
@@ -44,6 +60,8 @@ struct RewriteSystemBuilder {
4460 : Context(ctx), Dump(dump) {}
4561 void addGenericSignature (CanGenericSignature sig);
4662 void addProtocols (ArrayRef<const ProtocolDecl *> proto);
63+ void addProtocol (const ProtocolDecl *proto,
64+ bool initialComponent);
4765 void addAssociatedType (const AssociatedTypeDecl *type,
4866 const ProtocolDecl *proto);
4967 void addRequirement (const Requirement &req,
@@ -84,8 +102,11 @@ RewriteSystemBuilder::getConcreteSubstitutionSchema(CanType concreteType,
84102void RewriteSystemBuilder::addGenericSignature (CanGenericSignature sig) {
85103 // Collect all protocols transitively referenced from the generic signature's
86104 // requirements.
87- Protocols.visitRequirements (sig.getRequirements ());
88- Protocols.compute ();
105+ for (auto req : sig.getRequirements ()) {
106+ if (req.getKind () == RequirementKind::Conformance) {
107+ addProtocol (req.getProtocolDecl (), /* initialComponent=*/ false );
108+ }
109+ }
89110
90111 processProtocolDependencies ();
91112
@@ -97,8 +118,9 @@ void RewriteSystemBuilder::addGenericSignature(CanGenericSignature sig) {
97118void RewriteSystemBuilder::addProtocols (ArrayRef<const ProtocolDecl *> protos) {
98119 // Collect all protocols transitively referenced from this connected component
99120 // of the protocol dependency graph.
100- Protocols.visitProtocols (protos);
101- Protocols.compute ();
121+ for (auto proto : protos) {
122+ addProtocol (proto, /* initialComponent=*/ true );
123+ }
102124
103125 processProtocolDependencies ();
104126}
@@ -228,9 +250,27 @@ void RewriteSystemBuilder::addRequirement(const Requirement &req,
228250 RequirementRules.emplace_back (subjectTerm, constraintTerm);
229251}
230252
253+ // / Record information about a protocol if we have no seen it yet.
254+ void RewriteSystemBuilder::addProtocol (const ProtocolDecl *proto,
255+ bool initialComponent) {
256+ if (ProtocolMap.count (proto) > 0 )
257+ return ;
258+
259+ ProtocolMap[proto] = initialComponent;
260+ Protocols.push_back (proto);
261+ }
262+
231263void RewriteSystemBuilder::processProtocolDependencies () {
264+ unsigned i = 0 ;
265+ while (i < Protocols.size ()) {
266+ auto *proto = Protocols[i++];
267+ for (auto *depProto : proto->getProtocolDependencies ()) {
268+ addProtocol (depProto, /* initialComponent=*/ false );
269+ }
270+ }
271+
232272 // Add rewrite rules for each protocol.
233- for (auto *proto : Protocols. getProtocols () ) {
273+ for (auto *proto : Protocols) {
234274 if (Dump) {
235275 llvm::dbgs () << " protocol " << proto->getName () << " {\n " ;
236276 }
@@ -250,7 +290,7 @@ void RewriteSystemBuilder::processProtocolDependencies() {
250290 // Otherwise, we should either already have a requirement signature, or
251291 // we can trigger the computation of the requirement signatures of the
252292 // next component recursively.
253- if (Protocols. getProtocolInfo ( proto). InitialComponent ) {
293+ if (ProtocolMap[ proto] ) {
254294 for (auto req : proto->getStructuralRequirements ())
255295 addRequirement (req.req .getCanonical (), proto);
256296 } else {
0 commit comments