@@ -32,7 +32,23 @@ struct RewriteSystemBuilder {
32
32
RewriteContext &Context;
33
33
bool Dump;
34
34
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
+
36
52
std::vector<std::pair<MutableTerm, MutableTerm>> AssociatedTypeRules;
37
53
std::vector<std::pair<MutableTerm, MutableTerm>> RequirementRules;
38
54
@@ -44,6 +60,8 @@ struct RewriteSystemBuilder {
44
60
: Context(ctx), Dump(dump) {}
45
61
void addGenericSignature (CanGenericSignature sig);
46
62
void addProtocols (ArrayRef<const ProtocolDecl *> proto);
63
+ void addProtocol (const ProtocolDecl *proto,
64
+ bool initialComponent);
47
65
void addAssociatedType (const AssociatedTypeDecl *type,
48
66
const ProtocolDecl *proto);
49
67
void addRequirement (const Requirement &req,
@@ -84,8 +102,11 @@ RewriteSystemBuilder::getConcreteSubstitutionSchema(CanType concreteType,
84
102
void RewriteSystemBuilder::addGenericSignature (CanGenericSignature sig) {
85
103
// Collect all protocols transitively referenced from the generic signature's
86
104
// 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
+ }
89
110
90
111
processProtocolDependencies ();
91
112
@@ -97,8 +118,9 @@ void RewriteSystemBuilder::addGenericSignature(CanGenericSignature sig) {
97
118
void RewriteSystemBuilder::addProtocols (ArrayRef<const ProtocolDecl *> protos) {
98
119
// Collect all protocols transitively referenced from this connected component
99
120
// of the protocol dependency graph.
100
- Protocols.visitProtocols (protos);
101
- Protocols.compute ();
121
+ for (auto proto : protos) {
122
+ addProtocol (proto, /* initialComponent=*/ true );
123
+ }
102
124
103
125
processProtocolDependencies ();
104
126
}
@@ -228,9 +250,27 @@ void RewriteSystemBuilder::addRequirement(const Requirement &req,
228
250
RequirementRules.emplace_back (subjectTerm, constraintTerm);
229
251
}
230
252
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
+
231
263
void 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
+
232
272
// Add rewrite rules for each protocol.
233
- for (auto *proto : Protocols. getProtocols () ) {
273
+ for (auto *proto : Protocols) {
234
274
if (Dump) {
235
275
llvm::dbgs () << " protocol " << proto->getName () << " {\n " ;
236
276
}
@@ -250,7 +290,7 @@ void RewriteSystemBuilder::processProtocolDependencies() {
250
290
// Otherwise, we should either already have a requirement signature, or
251
291
// we can trigger the computation of the requirement signatures of the
252
292
// next component recursively.
253
- if (Protocols. getProtocolInfo ( proto). InitialComponent ) {
293
+ if (ProtocolMap[ proto] ) {
254
294
for (auto req : proto->getStructuralRequirements ())
255
295
addRequirement (req.req .getCanonical (), proto);
256
296
} else {
0 commit comments