@@ -616,34 +616,9 @@ void PropertyMap::concretizeTypeWitnessInConformance(
616
616
617
617
RewritePath path;
618
618
619
- auto simplify = [&](CanType t) -> CanType {
620
- return CanType (t.transformRec ([&](Type t) -> Optional<Type> {
621
- if (!t->isTypeParameter ())
622
- return None;
623
-
624
- auto term = Context.getRelativeTermForType (t->getCanonicalType (),
625
- substitutions);
626
- System.simplify (term);
627
- return Context.getTypeForTerm (term, { });
628
- }));
629
- };
630
-
631
- if (simplify (concreteType) == simplify (typeWitness) &&
632
- requirementKind == RequirementKind::SameType) {
633
- // FIXME: ConcreteTypeInDomainMap should support substitutions so
634
- // that we can remove this.
635
-
636
- if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
637
- llvm::dbgs () << " ^^ Type witness is the same as the concrete type\n " ;
638
- }
639
-
640
- // Add a rule T.[P:A] => T.
641
- constraintType = MutableTerm (key);
642
- } else {
643
- constraintType = computeConstraintTermForTypeWitness (
644
- key, concreteType, typeWitness, subjectType,
645
- substitutions, path);
646
- }
619
+ constraintType = computeConstraintTermForTypeWitness (
620
+ key, requirementKind, concreteType, typeWitness, subjectType,
621
+ substitutions, path);
647
622
648
623
inducedRules.emplace_back (constraintType, subjectType, path);
649
624
if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
@@ -721,9 +696,69 @@ RewriteSystem::getConcreteTypeWitness(unsigned index) const {
721
696
// /
722
697
// / T.[P:A] => V
723
698
MutableTerm PropertyMap::computeConstraintTermForTypeWitness (
724
- Term key, CanType concreteType, CanType typeWitness,
725
- const MutableTerm &subjectType, ArrayRef<Term> substitutions,
699
+ Term key, RequirementKind requirementKind,
700
+ CanType concreteType, CanType typeWitness,
701
+ const MutableTerm &subjectType,
702
+ ArrayRef<Term> substitutions,
726
703
RewritePath &path) const {
704
+ // If the type witness is abstract, introduce a same-type requirement
705
+ // between two type parameters.
706
+ if (typeWitness->isTypeParameter ()) {
707
+ // The type witness is a type parameter of the form τ_0_n.X.Y...Z,
708
+ // where 'n' is an index into the substitution array.
709
+ //
710
+ // Add a rule:
711
+ //
712
+ // T.[concrete: C : P].[P:X] => S[n].X.Y...Z
713
+ //
714
+ // Where S[n] is the nth substitution term.
715
+
716
+ // FIXME: Record a rewrite path.
717
+ return Context.getRelativeTermForType (typeWitness, substitutions);
718
+ }
719
+
720
+ // Otherwise the type witness is concrete, but may contain type
721
+ // parameters in structural position.
722
+
723
+ // Compute the concrete type symbol [concrete: C.X].
724
+ SmallVector<Term, 3 > result;
725
+ auto typeWitnessSchema =
726
+ remapConcreteSubstitutionSchema (typeWitness, substitutions,
727
+ Context, result);
728
+ auto typeWitnessSymbol =
729
+ Symbol::forConcreteType (typeWitnessSchema, result, Context);
730
+ System.simplifySubstitutions (typeWitnessSymbol);
731
+
732
+ auto concreteConformanceSymbol = *(subjectType.end () - 2 );
733
+ auto assocTypeSymbol = *(subjectType.end () - 1 );
734
+
735
+ RewriteSystem::ConcreteTypeWitness witness (concreteConformanceSymbol,
736
+ assocTypeSymbol,
737
+ typeWitnessSymbol);
738
+ unsigned witnessID = System.recordConcreteTypeWitness (witness);
739
+
740
+ // If it is equal to the parent type, introduce a same-type requirement
741
+ // between the two parameters.
742
+ if (requirementKind == RequirementKind::SameType &&
743
+ typeWitnessSymbol.getConcreteType () == concreteType &&
744
+ typeWitnessSymbol.getSubstitutions () == substitutions) {
745
+ // FIXME: ConcreteTypeInDomainMap should support substitutions so
746
+ // that we can remove this.
747
+
748
+ if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
749
+ llvm::dbgs () << " ^^ Type witness is the same as the concrete type\n " ;
750
+ }
751
+
752
+ // Add a rule T.[concrete: C : P].[P:X] => T.[concrete: C : P].
753
+ MutableTerm result (key);
754
+ result.add (concreteConformanceSymbol);
755
+
756
+ return result;
757
+ }
758
+
759
+ // If the type witness is completely concrete, try to introduce a
760
+ // same-type requirement with another representative type parameter,
761
+ // if we have one.
727
762
if (!typeWitness->hasTypeParameter ()) {
728
763
// Check if we have a shorter representative we can use.
729
764
auto domain = key.getRootProtocols ();
@@ -737,46 +772,23 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
737
772
llvm::dbgs () << " ^^ Type witness can re-use property bag of "
738
773
<< found->second << " \n " ;
739
774
}
775
+
776
+ // FIXME: Record a rewrite path.
740
777
return result;
741
778
}
742
779
}
743
780
}
744
781
745
- if (typeWitness->isTypeParameter ()) {
746
- // The type witness is a type parameter of the form τ_0_n.X.Y...Z,
747
- // where 'n' is an index into the substitution array.
748
- //
749
- // Add a rule:
750
- //
751
- // T.[concrete: C : P].[P:X] => S[n].X.Y...Z
752
- //
753
- // Where S[n] is the nth substitution term.
754
- return Context.getRelativeTermForType (typeWitness, substitutions);
755
- }
756
-
757
- // The type witness is a concrete type.
782
+ // Otherwise, add a concrete type requirement for the type witness.
758
783
//
759
784
// Add a rule:
760
785
//
761
- // T.[concrete: C : P].[P:X].[concrete: Foo.A ] => T.[concrete: C : P].[P:A ].
786
+ // T.[concrete: C : P].[P:X].[concrete: C.X ] => T.[concrete: C : P].[P:X ].
762
787
MutableTerm constraintType = subjectType;
763
-
764
- SmallVector<Term, 3 > result;
765
- auto typeWitnessSchema =
766
- remapConcreteSubstitutionSchema (typeWitness, substitutions,
767
- Context, result);
768
-
769
- constraintType.add (
770
- Symbol::forConcreteType (
771
- typeWitnessSchema, result, Context));
772
-
773
- RewriteSystem::ConcreteTypeWitness witness (*(constraintType.end () - 3 ),
774
- *(constraintType.end () - 2 ),
775
- *(constraintType.end () - 1 ));
776
- unsigned index = System.recordConcreteTypeWitness (witness);
788
+ constraintType.add (typeWitnessSymbol);
777
789
778
790
path.add (RewriteStep::forConcreteTypeWitness (
779
- index , /* inverse=*/ false ));
791
+ witnessID , /* inverse=*/ false ));
780
792
781
793
return constraintType;
782
794
}
0 commit comments