@@ -229,9 +229,72 @@ RequirementMachine::buildRequirementsFromRules(
229229 return reqs;
230230}
231231
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+
232294// / Builds the requirement signatures for each protocol in this strongly
233295// / connected component.
234- llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>>
296+ llvm::DenseMap<const ProtocolDecl *,
297+ RequirementMachine::MinimalProtocolRequirements>
235298RequirementMachine::computeMinimalProtocolRequirements () {
236299 auto protos = System.getProtocols ();
237300
@@ -249,13 +312,23 @@ RequirementMachine::computeMinimalProtocolRequirements() {
249312
250313 auto rules = System.getMinimizedProtocolRules ();
251314
315+ auto &ctx = Context.getASTContext ();
316+
252317 // Note that we build 'result' by iterating over 'protos' rather than
253318 // 'rules'; this is intentional, so that even if a protocol has no
254319 // 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;
256321 for (const auto *proto : protos) {
257322 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));
259332 }
260333
261334 return result;
@@ -311,32 +384,37 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
311384 // was kicked off with.
312385 ArrayRef<Requirement> result;
313386
387+ if (debug) {
388+ llvm::dbgs () << " \n Requirement signatures:\n " ;
389+ }
390+
314391 for (const auto &pair : minimalRequirements) {
315392 auto *otherProto = pair.first ;
316393 const auto &reqs = pair.second ;
317394
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-
322395 // Dump the result if requested.
323396 if (debug) {
324- llvm::dbgs () << " Protocol " << otherProto->getName () << " : " ;
397+ llvm::dbgs () << " - Protocol " << otherProto->getName () << " : " ;
325398
326399 auto sig = GenericSignature::get (
327400 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 " ;
330407 }
331408
332409 // Don't call setRequirementSignature() on the original proto; the
333410 // request evaluator will do it for us.
334411 if (otherProto == proto)
335- result = reqsCopy ;
412+ result = reqs. Requirements ;
336413 else {
414+ auto temp = reqs.Requirements ;
337415 ctx.evaluator .cacheOutput (
338416 RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
339- std::move (reqsCopy ));
417+ std::move (temp ));
340418 }
341419 }
342420
0 commit comments