@@ -614,42 +614,63 @@ void PropertyMap::concretizeTypeWitnessInConformance(
614
614
615
615
MutableTerm constraintType;
616
616
617
- auto simplify = [&](CanType t) -> CanType {
618
- return CanType (t.transformRec ([&](Type t) -> Optional<Type> {
619
- if (!t->isTypeParameter ())
620
- return None;
621
-
622
- auto term = Context.getRelativeTermForType (t->getCanonicalType (),
623
- substitutions);
624
- System.simplify (term);
625
- return Context.getTypeForTerm (term, { });
626
- }));
627
- };
628
-
629
- if (simplify (concreteType) == simplify (typeWitness) &&
630
- requirementKind == RequirementKind::SameType) {
631
- // FIXME: ConcreteTypeInDomainMap should support substitutions so
632
- // that we can remove this.
633
-
634
- if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
635
- llvm::dbgs () << " ^^ Type witness is the same as the concrete type\n " ;
636
- }
617
+ RewritePath path;
637
618
638
- // Add a rule T.[P:A] => T.
639
- constraintType = MutableTerm (key);
640
- } else {
641
- constraintType = computeConstraintTermForTypeWitness (
642
- key, concreteType, typeWitness, subjectType,
643
- substitutions);
644
- }
619
+ constraintType = computeConstraintTermForTypeWitness (
620
+ key, requirementKind, concreteType, typeWitness, subjectType,
621
+ substitutions, path);
645
622
646
- inducedRules.emplace_back (subjectType, constraintType );
623
+ inducedRules.emplace_back (constraintType, subjectType, path );
647
624
if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
648
625
llvm::dbgs () << " ^^ Induced rule " << constraintType
649
626
<< " => " << subjectType << " \n " ;
650
627
}
651
628
}
652
629
630
+ RewriteSystem::ConcreteTypeWitness::ConcreteTypeWitness (
631
+ Symbol concreteConformance,
632
+ Symbol assocType,
633
+ Symbol concreteType)
634
+ : ConcreteConformance(concreteConformance),
635
+ AssocType(assocType),
636
+ ConcreteType(concreteType) {
637
+ assert (concreteConformance.getKind () == Symbol::Kind::ConcreteConformance);
638
+ assert (assocType.getKind () == Symbol::Kind::AssociatedType);
639
+ assert (concreteType.getKind () == Symbol::Kind::ConcreteType);
640
+ assert (assocType.getProtocols ().size () == 1 );
641
+ assert (assocType.getProtocols ()[0 ] == concreteConformance.getProtocol ());
642
+ }
643
+
644
+ bool swift::rewriting::operator ==(
645
+ const RewriteSystem::ConcreteTypeWitness &lhs,
646
+ const RewriteSystem::ConcreteTypeWitness &rhs) {
647
+ return (lhs.ConcreteConformance == rhs.ConcreteConformance &&
648
+ lhs.AssocType == rhs.AssocType &&
649
+ lhs.ConcreteType == rhs.ConcreteType );
650
+ }
651
+
652
+ unsigned RewriteSystem::recordConcreteTypeWitness (
653
+ RewriteSystem::ConcreteTypeWitness witness) {
654
+ auto key = std::make_pair (witness.ConcreteConformance ,
655
+ witness.AssocType );
656
+ unsigned index = ConcreteTypeWitnesses.size ();
657
+ auto inserted = ConcreteTypeWitnessMap.insert (std::make_pair (key, index));
658
+
659
+ if (!inserted.second ) {
660
+ index = inserted.first ->second ;
661
+ } else {
662
+ ConcreteTypeWitnesses.push_back (witness);
663
+ }
664
+
665
+ assert (ConcreteTypeWitnesses[index] == witness);
666
+ return index;
667
+ }
668
+
669
+ const RewriteSystem::ConcreteTypeWitness &
670
+ RewriteSystem::getConcreteTypeWitness (unsigned index) const {
671
+ return ConcreteTypeWitnesses[index];
672
+ }
673
+
653
674
// / Given the key of a property bag known to have \p concreteType,
654
675
// / together with a \p typeWitness from a conformance on that concrete
655
676
// / type, return the right hand side of a rewrite rule to relate
@@ -675,8 +696,72 @@ void PropertyMap::concretizeTypeWitnessInConformance(
675
696
// /
676
697
// / T.[P:A] => V
677
698
MutableTerm PropertyMap::computeConstraintTermForTypeWitness (
678
- Term key, CanType concreteType, CanType typeWitness,
679
- const MutableTerm &subjectType, ArrayRef<Term> substitutions) const {
699
+ Term key, RequirementKind requirementKind,
700
+ CanType concreteType, CanType typeWitness,
701
+ const MutableTerm &subjectType,
702
+ ArrayRef<Term> substitutions,
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
+ path.add (RewriteStep::forSameTypeWitness (
757
+ witnessID, /* inverse=*/ true ));
758
+
759
+ return result;
760
+ }
761
+
762
+ // If the type witness is completely concrete, try to introduce a
763
+ // same-type requirement with another representative type parameter,
764
+ // if we have one.
680
765
if (!typeWitness->hasTypeParameter ()) {
681
766
// Check if we have a shorter representative we can use.
682
767
auto domain = key.getRootProtocols ();
@@ -690,38 +775,23 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
690
775
llvm::dbgs () << " ^^ Type witness can re-use property bag of "
691
776
<< found->second << " \n " ;
692
777
}
778
+
779
+ // FIXME: Record a rewrite path.
693
780
return result;
694
781
}
695
782
}
696
783
}
697
784
698
- if (typeWitness->isTypeParameter ()) {
699
- // The type witness is a type parameter of the form τ_0_n.X.Y...Z,
700
- // where 'n' is an index into the substitution array.
701
- //
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.
707
- return Context.getRelativeTermForType (typeWitness, substitutions);
708
- }
709
-
710
- // The type witness is a concrete type.
785
+ // Otherwise, add a concrete type requirement for the type witness.
711
786
//
712
787
// Add a rule:
713
788
//
714
- // T.[concrete: C : P].[P:X].[concrete: Foo.A ] => T.[concrete: C : P].[P:A ].
789
+ // T.[concrete: C : P].[P:X].[concrete: C.X ] => T.[concrete: C : P].[P:X ].
715
790
MutableTerm constraintType = subjectType;
791
+ constraintType.add (typeWitnessSymbol);
716
792
717
- SmallVector<Term, 3 > result;
718
- auto typeWitnessSchema =
719
- remapConcreteSubstitutionSchema (typeWitness, substitutions,
720
- Context, result);
721
-
722
- constraintType.add (
723
- Symbol::forConcreteType (
724
- typeWitnessSchema, result, Context));
793
+ path.add (RewriteStep::forConcreteTypeWitness (
794
+ witnessID, /* inverse=*/ false ));
725
795
726
796
return constraintType;
727
797
}
0 commit comments