@@ -229,9 +229,72 @@ RequirementMachine::buildRequirementsFromRules(
229
229
return reqs;
230
230
}
231
231
232
+ // / Convert a list of protocol typealias rules to a list of name/underlying type
233
+ // / pairs.
234
+ std::vector<std::pair<Identifier, Type>>
235
+ RequirementMachine::buildProtocolTypeAliasesFromRules (
236
+ ArrayRef<unsigned > rules,
237
+ TypeArrayView<GenericTypeParamType> genericParams) const {
238
+ std::vector<std::pair<Identifier, Type>> aliases;
239
+
240
+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
241
+ llvm::dbgs () << " \n Minimized type aliases:\n " ;
242
+ }
243
+
244
+ for (unsigned ruleID : rules) {
245
+ const auto &rule = System.getRule (ruleID);
246
+ auto name = *rule.isProtocolTypeAliasRule ();
247
+ Type underlyingType;
248
+
249
+ if (auto prop = rule.isPropertyRule ()) {
250
+ assert (prop->getKind () == Symbol::Kind::ConcreteType);
251
+
252
+ // Requirements containing unresolved name symbols originate from
253
+ // invalid code and should not appear in the generic signature.
254
+ for (auto term : prop->getSubstitutions ()) {
255
+ if (term.containsUnresolvedSymbols ())
256
+ continue ;
257
+ }
258
+
259
+ // Requirements containing error types originate from invalid code
260
+ // and should not appear in the generic signature.
261
+ if (prop->getConcreteType ()->hasError ())
262
+ continue ;
263
+
264
+ underlyingType = Map.getTypeFromSubstitutionSchema (
265
+ prop->getConcreteType (),
266
+ prop->getSubstitutions (),
267
+ genericParams, MutableTerm ());
268
+ } else {
269
+ underlyingType = Map.getTypeForTerm (rule.getRHS (), genericParams);
270
+ }
271
+
272
+ aliases.emplace_back (name, underlyingType);
273
+
274
+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
275
+ PrintOptions opts;
276
+ opts.ProtocolQualifiedDependentMemberTypes = true ;
277
+
278
+ llvm::dbgs () << " - " << name << " == " ;
279
+ underlyingType.print (llvm::dbgs (), opts);
280
+ llvm::dbgs () << " \n " ;
281
+ }
282
+ }
283
+
284
+ // Finally, sort the aliases in canonical order.
285
+ llvm::array_pod_sort (aliases.begin (), aliases.end (),
286
+ [](const std::pair<Identifier, Type> *lhs,
287
+ const std::pair<Identifier, Type> *rhs) -> int {
288
+ return lhs->first .compare (rhs->first );
289
+ });
290
+
291
+ return aliases;
292
+ }
293
+
232
294
// / Builds the requirement signatures for each protocol in this strongly
233
295
// / connected component.
234
- llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>>
296
+ llvm::DenseMap<const ProtocolDecl *,
297
+ RequirementMachine::MinimalProtocolRequirements>
235
298
RequirementMachine::computeMinimalProtocolRequirements () {
236
299
auto protos = System.getProtocols ();
237
300
@@ -249,13 +312,23 @@ RequirementMachine::computeMinimalProtocolRequirements() {
249
312
250
313
auto rules = System.getMinimizedProtocolRules ();
251
314
315
+ auto &ctx = Context.getASTContext ();
316
+
252
317
// Note that we build 'result' by iterating over 'protos' rather than
253
318
// 'rules'; this is intentional, so that even if a protocol has no
254
319
// rules, we still end up creating an entry for it in 'result'.
255
- llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement> > result;
320
+ llvm::DenseMap<const ProtocolDecl *, MinimalProtocolRequirements > result;
256
321
for (const auto *proto : protos) {
257
322
auto genericParams = proto->getGenericSignature ().getGenericParams ();
258
- result[proto] = buildRequirementsFromRules (rules[proto], genericParams);
323
+
324
+ result[proto].Requirements =
325
+ ctx.AllocateCopy (
326
+ buildRequirementsFromRules (rules[proto].Requirements ,
327
+ genericParams));
328
+ result[proto].TypeAliases =
329
+ ctx.AllocateCopy (
330
+ buildProtocolTypeAliasesFromRules (rules[proto].TypeAliases ,
331
+ genericParams));
259
332
}
260
333
261
334
return result;
@@ -311,32 +384,37 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
311
384
// was kicked off with.
312
385
ArrayRef<Requirement> result;
313
386
387
+ if (debug) {
388
+ llvm::dbgs () << " \n Requirement signatures:\n " ;
389
+ }
390
+
314
391
for (const auto &pair : minimalRequirements) {
315
392
auto *otherProto = pair.first ;
316
393
const auto &reqs = pair.second ;
317
394
318
- // setRequirementSignature() doesn't take ownership of the memory, so
319
- // we have to make a copy of the std::vector temporary.
320
- ArrayRef<Requirement> reqsCopy = ctx.AllocateCopy (reqs);
321
-
322
395
// Dump the result if requested.
323
396
if (debug) {
324
- llvm::dbgs () << " Protocol " << otherProto->getName () << " : " ;
397
+ llvm::dbgs () << " - Protocol " << otherProto->getName () << " : " ;
325
398
326
399
auto sig = GenericSignature::get (
327
400
otherProto->getGenericSignature ().getGenericParams (),
328
- reqsCopy);
329
- llvm::dbgs () << sig << " \n " ;
401
+ reqs.Requirements );
402
+
403
+ PrintOptions opts;
404
+ opts.ProtocolQualifiedDependentMemberTypes = true ;
405
+ sig.print (llvm::dbgs (), opts);
406
+ llvm::dbgs () << " \n " ;
330
407
}
331
408
332
409
// Don't call setRequirementSignature() on the original proto; the
333
410
// request evaluator will do it for us.
334
411
if (otherProto == proto)
335
- result = reqsCopy ;
412
+ result = reqs. Requirements ;
336
413
else {
414
+ auto temp = reqs.Requirements ;
337
415
ctx.evaluator .cacheOutput (
338
416
RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
339
- std::move (reqsCopy ));
417
+ std::move (temp ));
340
418
}
341
419
}
342
420
0 commit comments