@@ -854,26 +854,80 @@ Term RewriteContext::getTermForType(CanType paramType,
854
854
// / parameter atom.
855
855
// /
856
856
// / If \p proto is non-null, this is a term relative to a protocol's
857
- // / 'Self' type. The term is rooted in a protocol atom.
857
+ // / 'Self' type. The term is rooted in a protocol atom for this protocol,
858
+ // / or an associated type atom for some associated type in this protocol.
859
+ // /
860
+ // / Resolved DependentMemberTypes map to associated type atoms.
861
+ // / Unresolved DependentMemberTypes map to name atoms.
862
+ // /
863
+ // / Note the behavior of the root term is special if it is an associated
864
+ // / type atom. The protocol of the associated type is always mapped to
865
+ // / \p proto if it was provided. This ensures we get the correct behavior
866
+ // / if a protocol places a constraint on an associated type inherited from
867
+ // / another protocol:
868
+ // /
869
+ // / protocol P {
870
+ // / associatedtype Foo
871
+ // / }
872
+ // /
873
+ // / protocol Q : P where Foo : R {}
874
+ // /
875
+ // / protocol R {}
876
+ // /
877
+ // / The DependentMemberType in the requirement signature of Q refers to
878
+ // / P::Foo.
879
+ // /
880
+ // / However, we want Q's requirement signature to introduce the rewrite rule
881
+ // /
882
+ // / [Q:Foo].[R] => [Q:Foo]
883
+ // /
884
+ // / and not
885
+ // /
886
+ // / [P:Foo].[R] => [P:Foo]
887
+ // /
888
+ // / This is because the rule only applies to Q's logical override of Foo, and
889
+ // / not P's Foo.
890
+ // /
891
+ // / To handle this, getMutableTermForType() behaves as follows:
892
+ // /
893
+ // / Self.P::Foo with proto = P => [P:Foo]
894
+ // / Self.P::Foo with proto = Q => [Q:Foo]
895
+ // / τ_0_0.P::Foo with proto == nullptr => τ_0_0.[P:Foo]
858
896
// /
859
- // / The bound associated types in the interface type are ignored; the
860
- // / resulting term consists entirely of a root atom followed by zero
861
- // / or more name atoms.
862
897
MutableTerm RewriteContext::getMutableTermForType (CanType paramType,
863
898
const ProtocolDecl *proto) {
864
899
assert (paramType->isTypeParameter ());
865
900
866
901
// Collect zero or more nested type names in reverse order.
902
+ bool innermostAssocTypeWasResolved = false ;
903
+
867
904
SmallVector<Atom, 3 > atoms;
868
905
while (auto memberType = dyn_cast<DependentMemberType>(paramType)) {
869
- atoms.push_back (Atom::forName (memberType->getName (), *this ));
870
906
paramType = memberType.getBase ();
907
+
908
+ if (auto *assocType = memberType->getAssocType ()) {
909
+ const auto *thisProto = assocType->getProtocol ();
910
+ if (proto && isa<GenericTypeParamType>(paramType)) {
911
+ thisProto = proto;
912
+ innermostAssocTypeWasResolved = true ;
913
+ }
914
+ atoms.push_back (Atom::forAssociatedType (thisProto,
915
+ assocType->getName (),
916
+ *this ));
917
+ } else {
918
+ atoms.push_back (Atom::forName (memberType->getName (), *this ));
919
+ innermostAssocTypeWasResolved = false ;
920
+ }
871
921
}
872
922
873
923
// Add the root atom at the end.
874
924
if (proto) {
875
925
assert (proto->getSelfInterfaceType ()->isEqual (paramType));
876
- atoms.push_back (Atom::forProtocol (proto, *this ));
926
+
927
+ // Self.Foo becomes [P].Foo
928
+ // Self.Q::Foo becomes [P:Foo] (not [Q:Foo] or [P].[Q:Foo])
929
+ if (!innermostAssocTypeWasResolved)
930
+ atoms.push_back (Atom::forProtocol (proto, *this ));
877
931
} else {
878
932
atoms.push_back (Atom::forGenericParam (
879
933
cast<GenericTypeParamType>(paramType), *this ));
0 commit comments