@@ -541,32 +541,47 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
541541
542542 auto *concrete = conformance.getConcrete ();
543543
544- recordConcreteConformanceRule (concreteRuleID, conformanceRuleID, proto,
545- inducedRules);
546-
547544 // Record the conformance for use by
548545 // PropertyBag::getConformsToExcludingSuperclassConformances().
549546 conformances.push_back (concrete);
550547
548+ // All subsequent logic just records new rewrite rules, and can be
549+ // skipped if we've already processed this pair of rules.
550+ if (!ConcreteConformanceRules.insert (
551+ std::make_pair (concreteRuleID, conformanceRuleID)).second ) {
552+ // We've already processed this pair of rules.
553+ continue ;
554+ }
555+
556+ auto concreteConformanceSymbol = Symbol::forConcreteConformance (
557+ concreteType, substitutions, proto, Context);
558+
559+ recordConcreteConformanceRule (concreteRuleID, conformanceRuleID,
560+ requirementKind, concreteConformanceSymbol,
561+ inducedRules);
562+
551563 auto assocTypes = proto->getAssociatedTypeMembers ();
552564 if (assocTypes.empty ())
553565 continue ;
554566
555567 for (auto *assocType : assocTypes) {
556568 concretizeTypeWitnessInConformance (key, requirementKind,
557- concreteType, substitutions ,
558- proto, concrete, assocType,
569+ concreteConformanceSymbol ,
570+ concrete, assocType,
559571 inducedRules);
560572 }
561573 }
562574}
563575
564576void PropertyMap::concretizeTypeWitnessInConformance (
565577 Term key, RequirementKind requirementKind,
566- CanType concreteType, ArrayRef<Term> substitutions ,
567- const ProtocolDecl *proto, ProtocolConformance *concrete,
578+ Symbol concreteConformanceSymbol ,
579+ ProtocolConformance *concrete,
568580 AssociatedTypeDecl *assocType,
569581 SmallVectorImpl<InducedRule> &inducedRules) const {
582+ auto concreteType = concreteConformanceSymbol.getConcreteType ();
583+ auto substitutions = concreteConformanceSymbol.getSubstitutions ();
584+ auto *proto = concreteConformanceSymbol.getProtocol ();
570585
571586 if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
572587 llvm::dbgs () << " ^^ " << " Looking up type witness for "
@@ -591,7 +606,9 @@ void PropertyMap::concretizeTypeWitnessInConformance(
591606 << " of " << concreteType << " is " << typeWitness << " \n " ;
592607 }
593608
609+ // Build the term T.[concrete: C : P].[P:X].
594610 MutableTerm subjectType (key);
611+ subjectType.add (concreteConformanceSymbol);
595612 subjectType.add (Symbol::forAssociatedType (proto, assocType->getName (),
596613 Context));
597614
@@ -682,19 +699,26 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
682699 // The type witness is a type parameter of the form τ_0_n.X.Y...Z,
683700 // where 'n' is an index into the substitution array.
684701 //
685- // Add a rule T => S.X.Y...Z, where S is the nth substitution term.
702+ // Add a rule:
703+ //
704+ // T.[concrete: C : P].[P:X] => S[n].X.Y...Z
705+ //
706+ // Where S[n] is the nth substitution term.
686707 return Context.getRelativeTermForType (typeWitness, substitutions);
687708 }
688709
689710 // The type witness is a concrete type.
711+ //
712+ // Add a rule:
713+ //
714+ // T.[concrete: C : P].[P:X].[concrete: Foo.A] => T.[concrete: C : P].[P:A].
690715 MutableTerm constraintType = subjectType;
691716
692717 SmallVector<Term, 3 > result;
693718 auto typeWitnessSchema =
694719 remapConcreteSubstitutionSchema (typeWitness, substitutions,
695720 Context, result);
696721
697- // Add a rule T.[P:A].[concrete: Foo.A] => T.[P:A].
698722 constraintType.add (
699723 Symbol::forConcreteType (
700724 typeWitnessSchema, result, Context));
@@ -705,24 +729,28 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
705729void PropertyMap::recordConcreteConformanceRule (
706730 unsigned concreteRuleID,
707731 unsigned conformanceRuleID,
708- const ProtocolDecl *proto,
709- SmallVectorImpl<InducedRule> &inducedRules) {
710- if (!ConcreteConformanceRules.insert (
711- std::make_pair (concreteRuleID, conformanceRuleID)).second ) {
712- // We've already emitted this rule.
713- return ;
714- }
715-
732+ RequirementKind requirementKind,
733+ Symbol concreteConformanceSymbol,
734+ SmallVectorImpl<InducedRule> &inducedRules) const {
716735 const auto &concreteRule = System.getRule (concreteRuleID);
717736 const auto &conformanceRule = System.getRule (conformanceRuleID);
718737
719- auto conformanceSymbol = *conformanceRule.isPropertyRule ();
720- assert (conformanceSymbol.getKind () == Symbol::Kind::Protocol);
721- assert (conformanceSymbol.getProtocol () == proto);
722-
723- auto concreteSymbol = *concreteRule.isPropertyRule ();
724- assert (concreteSymbol.getKind () == Symbol::Kind::ConcreteType ||
725- concreteSymbol.getKind () == Symbol::Kind::Superclass);
738+ #ifndef NDEBUG
739+ {
740+ auto conformanceSymbol = *conformanceRule.isPropertyRule ();
741+ assert (conformanceSymbol.getKind () == Symbol::Kind::Protocol);
742+ assert (conformanceSymbol.getProtocol () ==
743+ concreteConformanceSymbol.getProtocol ());
744+
745+ auto concreteSymbol = *concreteRule.isPropertyRule ();
746+ if (concreteSymbol.getKind () == Symbol::Kind::Superclass)
747+ assert (requirementKind == RequirementKind::Superclass);
748+ else {
749+ assert (concreteSymbol.getKind () == Symbol::Kind::ConcreteType);
750+ assert (requirementKind == RequirementKind::SameType);
751+ }
752+ }
753+ #endif
726754
727755 RewritePath path;
728756
@@ -752,32 +780,18 @@ void PropertyMap::recordConcreteConformanceRule(
752780 // than T.
753781 unsigned adjustment = rhs.size () - concreteRule.getRHS ().size ();
754782 if (adjustment > 0 &&
755- !concreteSymbol .getSubstitutions ().empty ()) {
783+ !concreteConformanceSymbol .getSubstitutions ().empty ()) {
756784 path.add (RewriteStep::forAdjustment (adjustment, /* endOffset=*/ 1 ,
757785 /* inverse=*/ false ));
758-
759- concreteSymbol = concreteSymbol.prependPrefixToConcreteSubstitutions (
760- MutableTerm (rhs.begin (), rhs.begin () + adjustment),
761- Context);
762786 }
763787
764788 // Now, transform T''.[concrete: C].[P] into T''.[concrete: C : P].
765- Symbol concreteConformanceSymbol = [&]() {
766- if (concreteSymbol.getKind () == Symbol::Kind::ConcreteType) {
767- path.add (RewriteStep::forConcreteConformance (/* inverse=*/ false ));
768- return Symbol::forConcreteConformance (
769- concreteSymbol.getConcreteType (),
770- concreteSymbol.getSubstitutions (),
771- proto, Context);
772- } else {
773- assert (concreteSymbol.getKind () == Symbol::Kind::Superclass);
774- path.add (RewriteStep::forSuperclassConformance (/* inverse=*/ false ));
775- return Symbol::forConcreteConformance (
776- concreteSymbol.getSuperclass (),
777- concreteSymbol.getSubstitutions (),
778- proto, Context);
779- }
780- }();
789+ if (requirementKind == RequirementKind::Superclass) {
790+ path.add (RewriteStep::forSuperclassConformance (/* inverse=*/ false ));
791+ } else {
792+ assert (requirementKind == RequirementKind::SameType);
793+ path.add (RewriteStep::forConcreteConformance (/* inverse=*/ false ));
794+ }
781795
782796 MutableTerm lhs (rhs);
783797 lhs.add (concreteConformanceSymbol);
0 commit comments