@@ -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