@@ -632,6 +632,7 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParents(
632
632
633
633
concretizeNestedTypesFromConcreteParent (
634
634
equivClass->getKey (),
635
+ RequirementKind::SameType,
635
636
equivClass->ConcreteType ->getConcreteType (),
636
637
equivClass->ConcreteType ->getSubstitutions (),
637
638
equivClass->getConformsTo (),
@@ -645,6 +646,7 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParents(
645
646
646
647
concretizeNestedTypesFromConcreteParent (
647
648
equivClass->getKey (),
649
+ RequirementKind::Superclass,
648
650
equivClass->Superclass ->getSuperclass (),
649
651
equivClass->Superclass ->getSubstitutions (),
650
652
equivClass->getConformsTo (),
@@ -686,10 +688,13 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParents(
686
688
// / T.[P:B] => U.V
687
689
// /
688
690
void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent (
689
- const MutableTerm &key,
691
+ const MutableTerm &key, RequirementKind requirementKind,
690
692
CanType concreteType, ArrayRef<Term> substitutions,
691
693
ArrayRef<const ProtocolDecl *> conformsTo,
692
694
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) const {
695
+ assert (requirementKind == RequirementKind::SameType ||
696
+ requirementKind == RequirementKind::Superclass);
697
+
693
698
for (auto *proto : conformsTo) {
694
699
// FIXME: Either remove the ModuleDecl entirely from conformance lookup,
695
700
// or pass the correct one down in here.
@@ -745,9 +750,24 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
745
750
subjectType.add (Atom::forAssociatedType (proto, assocType->getName (),
746
751
Context));
747
752
748
- MutableTerm constraintType = computeConstraintTermForTypeWitness (
749
- key, concreteType, typeWitness, subjectType,
750
- substitutions);
753
+ MutableTerm constraintType;
754
+
755
+ if (concreteType == typeWitness &&
756
+ requirementKind == RequirementKind::SameType) {
757
+ // FIXME: ConcreteTypeInDomainMap should support substitutions so
758
+ // that we can remove this.
759
+
760
+ if (DebugConcretizeNestedTypes) {
761
+ llvm::dbgs () << " ^^ Type witness is the same as the concrete type\n " ;
762
+ }
763
+
764
+ // Add a rule T.[P:A] => T.
765
+ constraintType = key;
766
+ } else {
767
+ constraintType = computeConstraintTermForTypeWitness (
768
+ key, concreteType, typeWitness, subjectType,
769
+ substitutions);
770
+ }
751
771
752
772
inducedRules.emplace_back (subjectType, constraintType);
753
773
if (DebugConcretizeNestedTypes) {
@@ -775,25 +795,16 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
775
795
// /
776
796
// / T.[P:A].[concrete: Foo] => T.[P:A]
777
797
// /
778
- // / However, this also tries to tie off recursion first, using two
779
- // / heuristics:
780
- // /
781
- // / 1) If the type witness is the same exact type as the concrete type,
782
- // / we instead produce a rewrite rule:
798
+ // / However, this also tries to tie off recursion first using a heuristic.
783
799
// /
784
- // / T.[P:A] => T
785
- // /
786
- // / 2) If the type witness is fully concrete and we've already seen a
787
- // / shorter term V in the same domain with the same concrete type,
788
- // / we produce a rewrite rule:
800
+ // / If the type witness is fully concrete and we've already seen some
801
+ // / term V in the same domain with the same concrete type, we produce a
802
+ // / rewrite rule:
789
803
// /
790
804
// / T.[P:A] => V
791
805
MutableTerm EquivalenceClassMap::computeConstraintTermForTypeWitness (
792
- const MutableTerm &key,
793
- CanType concreteType,
794
- CanType typeWitness,
795
- const MutableTerm &subjectType,
796
- ArrayRef<Term> substitutions) const {
806
+ const MutableTerm &key, CanType concreteType, CanType typeWitness,
807
+ const MutableTerm &subjectType, ArrayRef<Term> substitutions) const {
797
808
if (!typeWitness->hasTypeParameter ()) {
798
809
// Check if we have a shorter representative we can use.
799
810
auto domain = key.getRootProtocols ();
@@ -811,20 +822,6 @@ MutableTerm EquivalenceClassMap::computeConstraintTermForTypeWitness(
811
822
}
812
823
}
813
824
814
- if (concreteType == typeWitness) {
815
- // FIXME: This is wrong for the superclass case!
816
- //
817
- // FIXME: ConcreteTypeInDomainMap should support substitutions so
818
- // that we can remove this.
819
-
820
- if (DebugConcretizeNestedTypes) {
821
- llvm::dbgs () << " ^^ Type witness is the same as the concrete type\n " ;
822
- }
823
-
824
- // Add a rule T.[P:A] => T.
825
- return key;
826
- }
827
-
828
825
if (typeWitness->isTypeParameter ()) {
829
826
// The type witness is a type parameter of the form τ_0_n.X.Y...Z,
830
827
// where 'n' is an index into the substitution array.
0 commit comments