@@ -616,34 +616,9 @@ void PropertyMap::concretizeTypeWitnessInConformance(
616616
617617 RewritePath path;
618618
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);
647622
648623 inducedRules.emplace_back (constraintType, subjectType, path);
649624 if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
@@ -721,9 +696,69 @@ RewriteSystem::getConcreteTypeWitness(unsigned index) const {
721696// /
722697// / T.[P:A] => V
723698MutableTerm 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,
726703 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.
727762 if (!typeWitness->hasTypeParameter ()) {
728763 // Check if we have a shorter representative we can use.
729764 auto domain = key.getRootProtocols ();
@@ -737,46 +772,23 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
737772 llvm::dbgs () << " ^^ Type witness can re-use property bag of "
738773 << found->second << " \n " ;
739774 }
775+
776+ // FIXME: Record a rewrite path.
740777 return result;
741778 }
742779 }
743780 }
744781
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.
758783 //
759784 // Add a rule:
760785 //
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 ].
762787 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);
777789
778790 path.add (RewriteStep::forConcreteTypeWitness (
779- index , /* inverse=*/ false ));
791+ witnessID , /* inverse=*/ false ));
780792
781793 return constraintType;
782794}
0 commit comments