@@ -1067,7 +1067,7 @@ void RuleBuilder::initWithGenericSignatureRequirements(
1067
1067
1068
1068
// Add rewrite rules for all top-level requirements.
1069
1069
for (const auto &req : requirements)
1070
- addRequirement (req, /* proto=*/ nullptr , /* requirementID= */ None );
1070
+ addRequirement (req, /* proto=*/ nullptr );
1071
1071
}
1072
1072
1073
1073
// / For building a rewrite system for a generic signature from user-written
@@ -1119,7 +1119,7 @@ void RuleBuilder::initWithProtocolSignatureRequirements(
1119
1119
1120
1120
auto reqs = proto->getRequirementSignature ();
1121
1121
for (auto req : reqs.getRequirements ())
1122
- addRequirement (req.getCanonical (), proto, /* requirementID= */ None );
1122
+ addRequirement (req.getCanonical (), proto);
1123
1123
for (auto alias : reqs.getTypeAliases ())
1124
1124
addTypeAlias (alias, proto);
1125
1125
@@ -1160,9 +1160,8 @@ void RuleBuilder::initWithProtocolWrittenRequirements(
1160
1160
1161
1161
for (auto req : proto->getStructuralRequirements ())
1162
1162
addRequirement (req, proto);
1163
-
1164
1163
for (auto req : proto->getTypeAliasRequirements ())
1165
- addRequirement (req.getCanonical (), proto, /* requirementID= */ None );
1164
+ addRequirement (req.getCanonical (), proto);
1166
1165
1167
1166
for (auto *otherProto : proto->getProtocolDependencies ())
1168
1167
addReferencedProtocol (otherProto);
@@ -1177,6 +1176,43 @@ void RuleBuilder::initWithProtocolWrittenRequirements(
1177
1176
collectRulesFromReferencedProtocols ();
1178
1177
}
1179
1178
1179
+ // / For adding conditional conformance requirements to an existing rewrite
1180
+ // / system. This might pull in additional protocols that we haven't seen
1181
+ // / before.
1182
+ // /
1183
+ // / The interface types in the requirements are converted to terms relative
1184
+ // / to the given array of substitutions, using
1185
+ // / RewriteContext::getRelativeTermForType().
1186
+ // /
1187
+ // / For example, given a concrete conformance rule:
1188
+ // /
1189
+ // / X.Y.[concrete: Array<X.Z> : Equatable]
1190
+ // /
1191
+ // / The substitutions are {τ_0_0 := X.Z}, and the Array : Equatable conformance
1192
+ // / has a conditional requirement 'τ_0_0 : Equatable', so the following
1193
+ // / conformance rule will be added:
1194
+ // /
1195
+ // / X.Z.[Equatable] => X.Z
1196
+ void RuleBuilder::initWithConditionalRequirements (
1197
+ ArrayRef<Requirement> requirements,
1198
+ ArrayRef<Term> substitutions) {
1199
+ assert (!Initialized);
1200
+ Initialized = 1 ;
1201
+
1202
+ // Collect all protocols transitively referenced from these requirements.
1203
+ for (auto req : requirements) {
1204
+ if (req.getKind () == RequirementKind::Conformance) {
1205
+ addReferencedProtocol (req.getProtocolDecl ());
1206
+ }
1207
+ }
1208
+
1209
+ collectRulesFromReferencedProtocols ();
1210
+
1211
+ // Add rewrite rules for all top-level requirements.
1212
+ for (const auto &req : requirements)
1213
+ addRequirement (req.getCanonical (), /* proto=*/ nullptr , substitutions);
1214
+ }
1215
+
1180
1216
// / Add permanent rules for a protocol, consisting of:
1181
1217
// /
1182
1218
// / - The identity conformance rule [P].[P] => [P].
@@ -1323,8 +1359,16 @@ swift::rewriting::getRuleForRequirement(const Requirement &req,
1323
1359
return std::make_pair (subjectTerm, constraintTerm);
1324
1360
}
1325
1361
1362
+ // / Convert a requirement to a rule and add it to the builder.
1363
+ // /
1364
+ // / The types in the requirement must be canonical.
1365
+ // /
1366
+ // / If \p substitutions is not None, the interface types in the requirement
1367
+ // / are converted to terms relative to these substitutions, using
1368
+ // / RewriteContext::getRelativeTermForType().
1326
1369
void RuleBuilder::addRequirement (const Requirement &req,
1327
1370
const ProtocolDecl *proto,
1371
+ Optional<ArrayRef<Term>> substitutions,
1328
1372
Optional<unsigned > requirementID) {
1329
1373
if (Dump) {
1330
1374
llvm::dbgs () << " + " ;
@@ -1333,8 +1377,7 @@ void RuleBuilder::addRequirement(const Requirement &req,
1333
1377
}
1334
1378
1335
1379
auto rule =
1336
- getRuleForRequirement (req, proto, /* substitutions=*/ None,
1337
- Context);
1380
+ getRuleForRequirement (req, proto, substitutions, Context);
1338
1381
RequirementRules.push_back (
1339
1382
std::make_tuple (rule.first , rule.second , requirementID));
1340
1383
}
@@ -1343,7 +1386,8 @@ void RuleBuilder::addRequirement(const StructuralRequirement &req,
1343
1386
const ProtocolDecl *proto) {
1344
1387
WrittenRequirements.push_back (req);
1345
1388
unsigned requirementID = WrittenRequirements.size () - 1 ;
1346
- addRequirement (req.req .getCanonical (), proto, requirementID);
1389
+ addRequirement (req.req .getCanonical (), proto, /* substitutions=*/ None,
1390
+ requirementID);
1347
1391
}
1348
1392
1349
1393
// / Lowers a protocol typealias to a rewrite rule.
0 commit comments