@@ -1051,7 +1051,7 @@ void RuleBuilder::addRequirements(ArrayRef<Requirement> requirements) {
1051
1051
// Collect all protocols transitively referenced from these requirements.
1052
1052
for (auto req : requirements) {
1053
1053
if (req.getKind () == RequirementKind::Conformance) {
1054
- addProtocol (req.getProtocolDecl (), /* initialComponent= */ false );
1054
+ addReferencedProtocol (req.getProtocolDecl ());
1055
1055
}
1056
1056
}
1057
1057
@@ -1066,7 +1066,7 @@ void RuleBuilder::addRequirements(ArrayRef<StructuralRequirement> requirements)
1066
1066
// Collect all protocols transitively referenced from these requirements.
1067
1067
for (auto req : requirements) {
1068
1068
if (req.req .getKind () == RequirementKind::Conformance) {
1069
- addProtocol (req.req .getProtocolDecl (), /* initialComponent= */ false );
1069
+ addReferencedProtocol (req.req .getProtocolDecl ());
1070
1070
}
1071
1071
}
1072
1072
@@ -1077,16 +1077,65 @@ void RuleBuilder::addRequirements(ArrayRef<StructuralRequirement> requirements)
1077
1077
addRequirement (req, /* proto=*/ nullptr );
1078
1078
}
1079
1079
1080
+ // / For building a rewrite system for a protocol connected component from
1081
+ // / user-written requirements. Used when actually building requirement
1082
+ // / signatures.
1080
1083
void RuleBuilder::addProtocols (ArrayRef<const ProtocolDecl *> protos) {
1081
- // Collect all protocols transitively referenced from this connected component
1082
- // of the protocol dependency graph.
1083
- for (auto proto : protos) {
1084
- addProtocol (proto, /* initialComponent=*/ true );
1084
+ for (auto *proto : protos) {
1085
+ ReferencedProtocols.insert (proto);
1086
+ }
1087
+
1088
+ for (auto *proto : protos) {
1089
+ if (Dump) {
1090
+ llvm::dbgs () << " protocol " << proto->getName () << " {\n " ;
1091
+ }
1092
+
1093
+ addPermanentProtocolRules (proto);
1094
+
1095
+ for (auto req : proto->getStructuralRequirements ())
1096
+ addRequirement (req, proto);
1097
+
1098
+ for (auto req : proto->getTypeAliasRequirements ())
1099
+ addRequirement (req.getCanonical (), proto, /* requirementID=*/ None);
1100
+
1101
+ for (auto *otherProto : proto->getProtocolDependencies ())
1102
+ addReferencedProtocol (otherProto);
1103
+
1104
+ if (Dump) {
1105
+ llvm::dbgs () << " }\n " ;
1106
+ }
1085
1107
}
1086
1108
1109
+ // Collect all protocols transitively referenced from this connected component
1110
+ // of the protocol dependency graph.
1087
1111
collectRulesFromReferencedProtocols ();
1088
1112
}
1089
1113
1114
+ // / Add permanent rules for a protocol, consisting of:
1115
+ // /
1116
+ // / - The identity conformance rule [P].[P] => [P].
1117
+ // / - An associated type introduction rule for each associated type.
1118
+ // / - An inherited associated type introduction rule for each associated
1119
+ // / type of each inherited protocol.
1120
+ void RuleBuilder::addPermanentProtocolRules (const ProtocolDecl *proto) {
1121
+ MutableTerm lhs;
1122
+ lhs.add (Symbol::forProtocol (proto, Context));
1123
+ lhs.add (Symbol::forProtocol (proto, Context));
1124
+
1125
+ MutableTerm rhs;
1126
+ rhs.add (Symbol::forProtocol (proto, Context));
1127
+
1128
+ PermanentRules.emplace_back (lhs, rhs);
1129
+
1130
+ for (auto *assocType : proto->getAssociatedTypeMembers ())
1131
+ addAssociatedType (assocType, proto);
1132
+
1133
+ for (auto *inheritedProto : Context.getInheritedProtocols (proto)) {
1134
+ for (auto *assocType : inheritedProto->getAssociatedTypeMembers ())
1135
+ addAssociatedType (assocType, proto);
1136
+ }
1137
+ }
1138
+
1090
1139
// / For an associated type T in a protocol P, we add a rewrite rule:
1091
1140
// /
1092
1141
// / [P].T => [P:T]
@@ -1264,72 +1313,44 @@ void RuleBuilder::addTypeAlias(const ProtocolTypeAlias &alias,
1264
1313
/* requirementID=*/ None);
1265
1314
}
1266
1315
1267
- // / Record information about a protocol if we have no seen it yet.
1268
- void RuleBuilder::addProtocol (const ProtocolDecl *proto,
1269
- bool initialComponent) {
1270
- if (ProtocolMap.count (proto) > 0 )
1271
- return ;
1272
-
1273
- ProtocolMap[proto] = initialComponent;
1274
- Protocols.push_back (proto);
1316
+ // / If we haven't seen this protocol yet, save it for later so that we can
1317
+ // / import the rewrite rules from its connected component.
1318
+ void RuleBuilder::addReferencedProtocol (const ProtocolDecl *proto) {
1319
+ if (ReferencedProtocols.insert (proto).second )
1320
+ ProtocolsToImport.push_back (proto);
1275
1321
}
1276
1322
1277
1323
// / Compute the transitive closure of the set of all protocols referenced from
1278
1324
// / the right hand sides of conformance requirements, and convert their
1279
1325
// / requirements to rewrite rules.
1280
1326
void RuleBuilder::collectRulesFromReferencedProtocols () {
1327
+ // Compute the transitive closure.
1281
1328
unsigned i = 0 ;
1282
- while (i < Protocols .size ()) {
1283
- auto *proto = Protocols [i++];
1329
+ while (i < ProtocolsToImport .size ()) {
1330
+ auto *proto = ProtocolsToImport [i++];
1284
1331
for (auto *depProto : proto->getProtocolDependencies ()) {
1285
- addProtocol (depProto, /* initialComponent= */ false );
1332
+ addReferencedProtocol (depProto);
1286
1333
}
1287
1334
}
1288
1335
1289
- // Add rewrite rules for each protocol.
1290
- for (auto *proto : Protocols) {
1336
+ // If this is a rewrite system for a generic signature, add rewrite rules for
1337
+ // each referenced protocol.
1338
+ //
1339
+ // if this is a rewrite system for a connected component of the protocol
1340
+ // dependency graph, add rewrite rules for each referenced protocol not part
1341
+ // of this connected component.
1342
+ for (auto *proto : ProtocolsToImport) {
1291
1343
if (Dump) {
1292
1344
llvm::dbgs () << " protocol " << proto->getName () << " {\n " ;
1293
1345
}
1294
1346
1295
- // Add the identity conformance rule [P].[P] => [P].
1296
- MutableTerm lhs;
1297
- lhs.add (Symbol::forProtocol (proto, Context));
1298
- lhs.add (Symbol::forProtocol (proto, Context));
1299
-
1300
- MutableTerm rhs;
1301
- rhs.add (Symbol::forProtocol (proto, Context));
1302
-
1303
- PermanentRules.emplace_back (lhs, rhs);
1304
-
1305
- for (auto *assocType : proto->getAssociatedTypeMembers ())
1306
- addAssociatedType (assocType, proto);
1307
-
1308
- for (auto *inheritedProto : Context.getInheritedProtocols (proto)) {
1309
- for (auto *assocType : inheritedProto->getAssociatedTypeMembers ())
1310
- addAssociatedType (assocType, proto);
1311
- }
1347
+ addPermanentProtocolRules (proto);
1312
1348
1313
- // If this protocol is part of the initial connected component, we're
1314
- // building requirement signatures for all protocols in this component,
1315
- // and so we must start with the structural requirements.
1316
- //
1317
- // Otherwise, we should either already have a requirement signature, or
1318
- // we can trigger the computation of the requirement signatures of the
1319
- // next component recursively.
1320
- if (ProtocolMap[proto]) {
1321
- for (auto req : proto->getStructuralRequirements ())
1322
- addRequirement (req, proto);
1323
-
1324
- for (auto req : proto->getTypeAliasRequirements ())
1325
- addRequirement (req.getCanonical (), proto, /* requirementID=*/ None);
1326
- } else {
1327
- auto reqs = proto->getRequirementSignature ();
1328
- for (auto req : reqs.getRequirements ())
1329
- addRequirement (req.getCanonical (), proto, /* requirementID=*/ None);
1330
- for (auto alias : reqs.getTypeAliases ())
1331
- addTypeAlias (alias, proto);
1332
- }
1349
+ auto reqs = proto->getRequirementSignature ();
1350
+ for (auto req : reqs.getRequirements ())
1351
+ addRequirement (req.getCanonical (), proto, /* requirementID=*/ None);
1352
+ for (auto alias : reqs.getTypeAliases ())
1353
+ addTypeAlias (alias, proto);
1333
1354
1334
1355
if (Dump) {
1335
1356
llvm::dbgs () << " }\n " ;
0 commit comments