@@ -93,23 +93,24 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
93
93
if (isPack ())
94
94
return getPack ()->subst (IFS);
95
95
96
- // Handle abstract conformances below:
96
+ ASSERT (isAbstract ());
97
+ auto *proto = getProtocol ();
97
98
98
99
// If the type is an opaque archetype, the conformance will remain abstract,
99
100
// 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);
104
104
}
105
105
}
106
106
107
+ // FIXME: Handle local archetypes as above!
108
+
107
109
// Otherwise, compute the substituted type.
108
110
auto substType = origType.subst (IFS);
109
111
110
- auto *proto = getProtocol ();
111
-
112
112
// If the type is an existential, it must be self-conforming.
113
+ // FIXME: This feels like it's in the wrong place.
113
114
if (substType->isExistentialType ()) {
114
115
auto optConformance =
115
116
lookupConformance (substType, proto, /* allowMissing=*/ true );
@@ -119,7 +120,7 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
119
120
return ProtocolConformanceRef::forInvalid ();
120
121
}
121
122
122
- // Check the conformance map.
123
+ // Local conformance lookup into the substitution map.
123
124
// FIXME: Pack element level?
124
125
return IFS.lookupConformance (origType->getCanonicalType (), substType, proto,
125
126
/* level=*/ 0 );
@@ -128,24 +129,20 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
128
129
ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext () const {
129
130
if (isConcrete ()) {
130
131
return getConcrete ()->subst (
131
- [](SubstitutableType *type) -> Type {
132
- if (auto *archetypeType = type->getAs <ArchetypeType>())
133
- return archetypeType->getInterfaceType ();
134
- return type;
135
- },
132
+ MapTypeOutOfContext (),
136
133
MakeAbstractConformanceForGenericType (),
137
134
SubstFlags::PreservePackExpansionLevel |
138
135
SubstFlags::SubstitutePrimaryArchetypes);
139
136
} else if (isPack ()) {
140
137
return getPack ()->subst (
141
- [](SubstitutableType *type) -> Type {
142
- if (auto *archetypeType = type->getAs <ArchetypeType>())
143
- return archetypeType->getInterfaceType ();
144
- return type;
145
- },
138
+ MapTypeOutOfContext (),
146
139
MakeAbstractConformanceForGenericType (),
147
140
SubstFlags::PreservePackExpansionLevel |
148
141
SubstFlags::SubstitutePrimaryArchetypes);
142
+ } else if (isAbstract ()) {
143
+ auto *abstract = getAbstract ();
144
+ return forAbstract (abstract->getType ()->mapTypeOutOfContext (),
145
+ abstract->getProtocol ());
149
146
}
150
147
151
148
return *this ;
@@ -266,6 +263,15 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
266
263
return conformance->getAssociatedConformance (assocType, protocol);
267
264
}
268
265
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
+
269
275
// An associated conformance of an archetype might be known to be
270
276
// a concrete conformance, if the subject type is fixed to a concrete
271
277
// type in the archetype's generic signature. We don't actually have
@@ -276,15 +282,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
276
282
// conformances where they store their subject types, we can also
277
283
// cache the lookups inside the abstract conformance instance too.
278
284
if (auto archetypeType = conformingType->getAs <ArchetypeType>()) {
279
- conformingType = archetypeType->getInterfaceType ();
280
285
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 ());
288
287
289
288
return lookupConformance (
290
289
genericEnv->mapTypeIntoContext (subjectType),
@@ -296,12 +295,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
296
295
// signature of the substitution (or in the case of type variables,
297
296
// we have no visibility into constraints). See the parallel hack
298
297
// 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);
305
300
}
306
301
307
302
// / Check of all types used by the conformance are canonical.
0 commit comments