@@ -93,23 +93,24 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
9393  if  (isPack ())
9494    return  getPack ()->subst (IFS);
9595
96-   //  Handle abstract conformances below:
96+   ASSERT (isAbstract ());
97+   auto  *proto = getProtocol ();
9798
9899  //  If the type is an opaque archetype, the conformance will remain abstract,
99100  //  unless we're specifically substituting opaque types.
100-   if  (auto  origArchetype = origType->getAs <ArchetypeType>()) {
101-     if  (!IFS.shouldSubstituteOpaqueArchetypes ()
102-         && isa<OpaqueTypeArchetypeType>(origArchetype)) {
103-       return  *this ;
101+   if  (auto  origArchetype = origType->getAs <OpaqueTypeArchetypeType>()) {
102+     if  (!IFS.shouldSubstituteOpaqueArchetypes ()) {
103+       return  forAbstract (origType.subst (IFS), proto);
104104    }
105105  }
106106
107+   //  FIXME: Handle local archetypes as above!
108+ 
107109  //  Otherwise, compute the substituted type.
108110  auto  substType = origType.subst (IFS);
109111
110-   auto  *proto = getProtocol ();
111- 
112112  //  If the type is an existential, it must be self-conforming.
113+   //  FIXME: This feels like it's in the wrong place.
113114  if  (substType->isExistentialType ()) {
114115    auto  optConformance =
115116        lookupConformance (substType, proto, /* allowMissing=*/ true );
@@ -119,7 +120,7 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
119120    return  ProtocolConformanceRef::forInvalid ();
120121  }
121122
122-   //  Check  the conformance  map.
123+   //  Local conformance lookup into  the substitution  map.
123124  //  FIXME: Pack element level?
124125  return  IFS.lookupConformance (origType->getCanonicalType (), substType, proto,
125126                               /* level=*/ 0 );
@@ -128,24 +129,20 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
128129ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext () const  {
129130  if  (isConcrete ()) {
130131    return  getConcrete ()->subst (
131-         [](SubstitutableType *type) -> Type {
132-           if  (auto  *archetypeType = type->getAs <ArchetypeType>())
133-             return  archetypeType->getInterfaceType ();
134-           return  type;
135-         },
132+         MapTypeOutOfContext (),
136133        MakeAbstractConformanceForGenericType (),
137134        SubstFlags::PreservePackExpansionLevel |
138135        SubstFlags::SubstitutePrimaryArchetypes);
139136  } else  if  (isPack ()) {
140137    return  getPack ()->subst (
141-         [](SubstitutableType *type) -> Type {
142-           if  (auto  *archetypeType = type->getAs <ArchetypeType>())
143-             return  archetypeType->getInterfaceType ();
144-           return  type;
145-         },
138+         MapTypeOutOfContext (),
146139        MakeAbstractConformanceForGenericType (),
147140        SubstFlags::PreservePackExpansionLevel |
148141        SubstFlags::SubstitutePrimaryArchetypes);
142+   } else  if  (isAbstract ()) {
143+     auto  *abstract = getAbstract ();
144+     return  forAbstract (abstract->getType ()->mapTypeOutOfContext (),
145+                        abstract->getProtocol ());
149146  }
150147
151148  return  *this ;
@@ -266,6 +263,15 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
266263    return  conformance->getAssociatedConformance (assocType, protocol);
267264  }
268265
266+   auto  computeSubjectType = [&](Type conformingType) -> Type {
267+     return  assocType.transformRec (
268+       [&](TypeBase *t) -> std::optional<Type> {
269+         if  (isa<GenericTypeParamType>(t))
270+           return  conformingType;
271+         return  std::nullopt ;
272+       });
273+   };
274+ 
269275  //  An associated conformance of an archetype might be known to be
270276  //  a concrete conformance, if the subject type is fixed to a concrete
271277  //  type in the archetype's generic signature. We don't actually have
@@ -276,15 +282,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
276282  //  conformances where they store their subject types, we can also
277283  //  cache the lookups inside the abstract conformance instance too.
278284  if  (auto  archetypeType = conformingType->getAs <ArchetypeType>()) {
279-     conformingType = archetypeType->getInterfaceType ();
280285    auto  *genericEnv = archetypeType->getGenericEnvironment ();
281- 
282-     auto  subjectType = assocType.transformRec (
283-       [&](TypeBase *t) -> std::optional<Type> {
284-         if  (isa<GenericTypeParamType>(t))
285-           return  conformingType;
286-         return  std::nullopt ;
287-       });
286+     auto  subjectType = computeSubjectType (archetypeType->getInterfaceType ());
288287
289288    return  lookupConformance (
290289        genericEnv->mapTypeIntoContext (subjectType),
@@ -296,12 +295,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
296295  //  signature of the substitution (or in the case of type variables,
297296  //  we have no visibility into constraints). See the parallel hack
298297  //  to handle this in SubstitutionMap::lookupConformance().
299-   CONDITIONAL_ASSERT (conformingType->isTypeParameter () ||
300-                      conformingType->isTypeVariableOrMember () ||
301-                      conformingType->is <UnresolvedType>() ||
302-                      conformingType->is <PlaceholderType>());
303- 
304-   return  ProtocolConformanceRef::forAbstract (conformingType, protocol);
298+   auto  subjectType = computeSubjectType (conformingType);
299+   return  ProtocolConformanceRef::forAbstract (subjectType, protocol);
305300}
306301
307302// / Check of all types used by the conformance are canonical.
0 commit comments