@@ -938,6 +938,156 @@ MutableTerm RewriteContext::getMutableTermForType(CanType paramType,
938938 return MutableTerm (atoms);
939939}
940940
941+ // / Compute the interface type for a range of atoms, with an optional
942+ // / root type.
943+ // /
944+ // / If the root type is specified, we wrap it in a series of
945+ // / DependentMemberTypes. Otherwise, the root is computed from
946+ // / the first atom of the range.
947+ template <typename Iter>
948+ Type getTypeForAtomRange (Iter begin, Iter end, Type root,
949+ TypeArrayView<GenericTypeParamType> genericParams,
950+ const ProtocolGraph &protos,
951+ ASTContext &ctx) {
952+ Type result = root;
953+
954+ auto handleRoot = [&](GenericTypeParamType *genericParam) {
955+ assert (genericParam->isCanonical ());
956+
957+ if (!genericParams.empty ()) {
958+ // Return a sugared GenericTypeParamType if we're given an array of
959+ // sugared types to substitute.
960+ unsigned index = GenericParamKey (genericParam).findIndexIn (genericParams);
961+ result = genericParams[index];
962+ return ;
963+ }
964+
965+ // Otherwise, we're going to return a canonical type.
966+ result = genericParam;
967+ };
968+
969+ for (; begin != end; ++begin) {
970+ auto atom = *begin;
971+
972+ if (!result) {
973+ // A valid term always begins with a generic parameter, protocol or
974+ // associated type atom.
975+ switch (atom.getKind ()) {
976+ case Atom::Kind::GenericParam:
977+ handleRoot (atom.getGenericParam ());
978+ continue ;
979+
980+ case Atom::Kind::Protocol:
981+ handleRoot (GenericTypeParamType::get (0 , 0 , ctx));
982+ continue ;
983+
984+ case Atom::Kind::AssociatedType:
985+ handleRoot (GenericTypeParamType::get (0 , 0 , ctx));
986+
987+ // An associated type term at the root means we have a dependent
988+ // member type rooted at Self; handle the associated type below.
989+ break ;
990+
991+ case Atom::Kind::Name:
992+ case Atom::Kind::Layout:
993+ case Atom::Kind::Superclass:
994+ case Atom::Kind::ConcreteType:
995+ llvm_unreachable (" Term has invalid root atom" );
996+ }
997+ }
998+
999+ // An unresolved type can appear if we have invalid requirements.
1000+ if (atom.getKind () == Atom::Kind::Name) {
1001+ result = DependentMemberType::get (result, atom.getName ());
1002+ continue ;
1003+ }
1004+
1005+ // We should have a resolved type at this point.
1006+ assert (atom.getKind () == Atom::Kind::AssociatedType);
1007+ auto *proto = atom.getProtocols ()[0 ];
1008+ auto name = atom.getName ();
1009+
1010+ AssociatedTypeDecl *assocType = nullptr ;
1011+
1012+ // Special case: handle unknown protocols, since they can appear in the
1013+ // invalid types that getCanonicalTypeInContext() must handle via
1014+ // concrete substitution; see the definition of getCanonicalTypeInContext()
1015+ // below for details.
1016+ if (!protos.isKnownProtocol (proto)) {
1017+ assert (root &&
1018+ " We only allow unknown protocols in getRelativeTypeForTerm()" );
1019+ assert (atom.getProtocols ().size () == 1 &&
1020+ " Unknown associated type atom must have a single protocol" );
1021+ assocType = proto->getAssociatedType (name)->getAssociatedTypeAnchor ();
1022+ } else {
1023+ // FIXME: Cache this
1024+ //
1025+ // An associated type atom [P1&P1&...&Pn:A] has one or more protocols
1026+ // P0...Pn and an identifier 'A'.
1027+ //
1028+ // We map it back to a AssociatedTypeDecl as follows:
1029+ //
1030+ // - For each protocol Pn, look for associated types A in Pn itself,
1031+ // and all protocols that Pn refines.
1032+ //
1033+ // - For each candidate associated type An in protocol Qn where
1034+ // Pn refines Qn, get the associated type anchor An' defined in
1035+ // protocol Qn', where Qn refines Qn'.
1036+ //
1037+ // - Out of all the candidiate pairs (Qn', An'), pick the one where
1038+ // the protocol Qn' is the lowest element according to the linear
1039+ // order defined by TypeDecl::compare().
1040+ //
1041+ // The associated type An' is then the canonical associated type
1042+ // representative of the associated type atom [P0&...&Pn:A].
1043+ //
1044+ for (auto *proto : atom.getProtocols ()) {
1045+ const auto &info = protos.getProtocolInfo (proto);
1046+ for (auto *otherAssocType : info.AssociatedTypes ) {
1047+ otherAssocType = otherAssocType->getAssociatedTypeAnchor ();
1048+
1049+ if (otherAssocType->getName () == name &&
1050+ (assocType == nullptr ||
1051+ TypeDecl::compare (otherAssocType->getProtocol (),
1052+ assocType->getProtocol ()) < 0 )) {
1053+ assocType = otherAssocType;
1054+ }
1055+ }
1056+ }
1057+ }
1058+
1059+ assert (assocType && " Need to look harder" );
1060+ result = DependentMemberType::get (result, assocType);
1061+ }
1062+
1063+ return result;
1064+ }
1065+
1066+ Type RewriteContext::getTypeForTerm (Term term,
1067+ TypeArrayView<GenericTypeParamType> genericParams,
1068+ const ProtocolGraph &protos) const {
1069+ return getTypeForAtomRange (term.begin (), term.end (), Type (),
1070+ genericParams, protos, Context);
1071+ }
1072+
1073+ Type RewriteContext::getTypeForTerm (const MutableTerm &term,
1074+ TypeArrayView<GenericTypeParamType> genericParams,
1075+ const ProtocolGraph &protos) const {
1076+ return getTypeForAtomRange (term.begin (), term.end (), Type (),
1077+ genericParams, protos, Context);
1078+ }
1079+
1080+ Type RewriteContext::getRelativeTypeForTerm (
1081+ const MutableTerm &term, const MutableTerm &prefix,
1082+ const ProtocolGraph &protos) const {
1083+ assert (std::equal (prefix.begin (), prefix.end (), term.begin ()));
1084+
1085+ auto genericParam = CanGenericTypeParamType::get (0 , 0 , Context);
1086+ return getTypeForAtomRange (
1087+ term.begin () + prefix.size (), term.end (), genericParam,
1088+ { }, protos, Context);
1089+ }
1090+
9411091void Rule::dump (llvm::raw_ostream &out) const {
9421092 out << LHS << " => " << RHS;
9431093 if (deleted)
0 commit comments