@@ -143,6 +143,67 @@ Type EquivalenceClass::getConcreteType(
143
143
ctx);
144
144
}
145
145
146
+ // / Computes the term corresponding to a member type access on a substitution.
147
+ // /
148
+ // / The type witness is a type parameter of the form τ_0_n.X.Y.Z,
149
+ // / where 'n' is an index into the substitution array.
150
+ // /
151
+ // / If the nth entry in the array is S, this will produce S.X.Y.Z.
152
+ // /
153
+ // / There is a special behavior if the substitution is a term consisting of a
154
+ // / single protocol atom [P]. If the innermost associated type in
155
+ // / \p typeWitness is [Q:Foo], the result will be [P:Foo], not [P].[Q:Foo] or
156
+ // / [Q:Foo].
157
+ static MutableTerm getRelativeTermForType (CanType typeWitness,
158
+ ArrayRef<Term> substitutions,
159
+ RewriteContext &ctx) {
160
+ MutableTerm result;
161
+
162
+ // Get the substitution S corresponding to τ_0_n.
163
+ unsigned index = getGenericParamIndex (typeWitness->getRootGenericParam ());
164
+ result = MutableTerm (substitutions[index]);
165
+
166
+ // If the substitution is a term consisting of a single protocol atom
167
+ // [P], save P for later.
168
+ const ProtocolDecl *proto = nullptr ;
169
+ if (result.size () == 1 &&
170
+ result[0 ].getKind () == Atom::Kind::Protocol) {
171
+ proto = result[0 ].getProtocol ();
172
+ }
173
+
174
+ // Collect zero or more member type names in reverse order.
175
+ SmallVector<Atom, 3 > atoms;
176
+ while (auto memberType = dyn_cast<DependentMemberType>(typeWitness)) {
177
+ typeWitness = memberType.getBase ();
178
+
179
+ auto *assocType = memberType->getAssocType ();
180
+ assert (assocType != nullptr &&
181
+ " Conformance checking should not produce unresolved member types" );
182
+
183
+ // If the substitution is a term consisting of a single protocol atom [P],
184
+ // produce [P:Foo] instead of [P].[Q:Foo] or [Q:Foo].
185
+ const auto *thisProto = assocType->getProtocol ();
186
+ if (proto && isa<GenericTypeParamType>(typeWitness)) {
187
+ thisProto = proto;
188
+
189
+ assert (result.size () == 1 );
190
+ assert (result[0 ].getKind () == Atom::Kind::Protocol);
191
+ assert (result[0 ].getProtocol () == proto);
192
+ result = MutableTerm ();
193
+ }
194
+
195
+ atoms.push_back (Atom::forAssociatedType (thisProto,
196
+ assocType->getName (), ctx));
197
+ }
198
+
199
+ // Add the member type names.
200
+ std::reverse (atoms.begin (), atoms.end ());
201
+ for (auto atom : atoms)
202
+ result.add (atom);
203
+
204
+ return result;
205
+ }
206
+
146
207
// / Given a concrete type that is a structural sub-component of a concrete
147
208
// / type produced by RewriteSystemBuilder::getConcreteSubstitutionSchema(),
148
209
// / collect the subset of referenced substitutions and renumber the generic
@@ -607,23 +668,9 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
607
668
// The type witness is a type parameter of the form τ_0_n.X.Y...Z,
608
669
// where 'n' is an index into the substitution array.
609
670
//
610
- // Collect zero or more member type names in reverse order.
611
- SmallVector<Atom, 3 > atoms;
612
- while (auto memberType = dyn_cast<DependentMemberType>(typeWitness)) {
613
- atoms.push_back (Atom::forName (memberType->getName (), Context));
614
- typeWitness = memberType.getBase ();
615
- }
616
-
617
- // Get the substitution S corresponding to τ_0_n.
618
- unsigned index = getGenericParamIndex (typeWitness);
619
- constraintType = MutableTerm (substitutions[index]);
620
-
621
- // Add the member type names.
622
- std::reverse (atoms.begin (), atoms.end ());
623
- for (auto atom : atoms)
624
- constraintType.add (atom);
625
-
626
- // Add a rule T => S.X.Y...Z.
671
+ // Add a rule T => S.X.Y...Z, where S is the nth substitution term.
672
+ constraintType = getRelativeTermForType (typeWitness, substitutions,
673
+ Context);
627
674
628
675
} else {
629
676
// The type witness is a concrete type.
@@ -635,12 +682,11 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
635
682
remapConcreteSubstitutionSchema (typeWitness, substitutions,
636
683
Context.getASTContext (),
637
684
result);
685
+
686
+ // Add a rule T.[P:A].[concrete: Foo.A] => T.[P:A].
638
687
constraintType.add (
639
688
Atom::forConcreteType (
640
689
typeWitnessSchema, result, Context));
641
-
642
- // Add a rule T.[P:A].[concrete: Foo.A] => T.[P:A].
643
-
644
690
}
645
691
646
692
inducedRules.emplace_back (subjectType, constraintType);
0 commit comments