@@ -75,7 +75,9 @@ void GenericEnvironment::addMapping(GenericParamKey key,
75
75
assert (genericParams[index] == key && " Bad generic parameter" );
76
76
77
77
// Add the mapping from the generic parameter to the context type.
78
- assert (getContextTypes ()[index].isNull () && " Already recoded this mapping" );
78
+ assert (getContextTypes ()[index].isNull () ||
79
+ getContextTypes ()[index]->is <ErrorType>() &&
80
+ " Already recoded this mapping" );
79
81
getContextTypes ()[index] = contextType;
80
82
}
81
83
@@ -121,6 +123,8 @@ Type TypeBase::mapTypeOutOfContext() {
121
123
Type
122
124
GenericEnvironment::getOrCreateArchetypeFromInterfaceType (Type depType) {
123
125
auto &builder = *getGenericSignatureBuilder ();
126
+ auto &ctx = builder.getASTContext ();
127
+
124
128
auto resolved =
125
129
builder.maybeResolveEquivalenceClass (
126
130
depType,
@@ -129,122 +133,86 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
129
133
if (!resolved)
130
134
return ErrorType::get (depType);
131
135
132
- if (auto concrete = resolved.getAsConcreteType ())
133
- return concrete;
136
+ if (auto concrete = resolved.getAsConcreteType ()) {
137
+ return mapTypeIntoContext (concrete,
138
+ builder.getLookupConformanceFn ());
139
+ }
134
140
135
141
auto *equivClass = resolved.getEquivalenceClass (builder);
136
142
137
143
auto genericParams = getGenericParams ();
138
144
Type anchor = equivClass->getAnchor (builder, genericParams);
139
145
140
- // If this equivalence class is mapped to a concrete type, produce that
141
- // type.
142
- if (equivClass->concreteType ) {
143
- if (equivClass->recursiveConcreteType )
144
- return ErrorType::get (anchor);
145
-
146
- // Prevent recursive substitution.
147
- equivClass->recursiveConcreteType = true ;
148
- SWIFT_DEFER {
149
- equivClass->recursiveConcreteType = false ;
150
- };
151
-
152
- return mapTypeIntoContext (equivClass->concreteType ,
153
- builder.getLookupConformanceFn ());
154
- }
155
-
156
- // Local function to check whether we have a generic parameter that has
157
- // already been recorded
158
- auto getAlreadyRecoveredGenericParam = [&]() -> Type {
159
- auto genericParam = anchor->getAs <GenericTypeParamType>();
160
- if (!genericParam) return Type ();
161
-
162
- auto type = getMappingIfPresent (genericParam);
163
- if (!type) return Type ();
164
-
165
- // We already have a mapping for this generic parameter in the generic
166
- // environment. Return it.
167
- return *type;
168
- };
169
-
170
- AssociatedTypeDecl *assocType = nullptr ;
146
+ // First, write an ErrorType to the location where this type is cached,
147
+ // to catch re-entrant lookups that might arise from an invalid generic
148
+ // signature (eg, <X where X == Array<X>>).
171
149
ArchetypeType *parentArchetype = nullptr ;
150
+ GenericTypeParamType *genericParam = nullptr ;
172
151
if (auto depMemTy = anchor->getAs <DependentMemberType>()) {
173
- // Map the parent type into this context.
174
152
parentArchetype =
175
153
getOrCreateArchetypeFromInterfaceType (depMemTy->getBase ())
176
154
->getAs <ArchetypeType>();
177
155
if (!parentArchetype)
178
156
return ErrorType::get (depMemTy);
179
157
180
- // If we already have a nested type with this name, return it.
181
- assocType = depMemTy->getAssocType ();
182
- if (auto nested =
183
- parentArchetype->getNestedTypeIfKnown (assocType->getName ())) {
184
- return *nested;
185
- }
158
+ auto name = depMemTy->getName ();
159
+ if (auto type = parentArchetype->getNestedTypeIfKnown (name))
160
+ return *type;
186
161
187
- // We will build the archetype below.
188
- } else if (auto result = getAlreadyRecoveredGenericParam ()) {
189
- // Return already-contextualized generic type parameter.
190
- return result;
162
+ parentArchetype->registerNestedType (name, ErrorType::get (ctx));
163
+ } else {
164
+ genericParam = anchor->castTo <GenericTypeParamType>();
165
+ if (auto type = getMappingIfPresent (genericParam))
166
+ return *type;
167
+ addMapping (genericParam, ErrorType::get (ctx));
191
168
}
192
169
193
- // Substitute into the superclass.
194
- Type superclass = (equivClass->recursiveSuperclassType
195
- ? Type () : equivClass->superclass );
196
- if (superclass && superclass->hasTypeParameter ()) {
197
- // Prevent recursive substitution.
198
- equivClass->recursiveSuperclassType = true ;
199
- SWIFT_DEFER {
200
- equivClass->recursiveSuperclassType = false ;
201
- };
202
-
203
- superclass = mapTypeIntoContext (superclass,
204
- builder.getLookupConformanceFn ());
205
- if (superclass->is <ErrorType>())
206
- superclass = Type ();
207
-
208
- // We might have recursively recorded the archetype; if so, return early.
209
- // FIXME: This should be detectable before we end up building archetypes.
210
- if (auto result = getAlreadyRecoveredGenericParam ())
211
- return result;
212
- }
170
+ Type result;
213
171
214
- // Build a new archetype.
172
+ // If this equivalence class is mapped to a concrete type, produce that
173
+ // type.
174
+ if (equivClass->concreteType ) {
175
+ result = mapTypeIntoContext (equivClass->concreteType ,
176
+ builder.getLookupConformanceFn ());
177
+ } else {
178
+ // Substitute into the superclass.
179
+ Type superclass = equivClass->superclass ;
180
+ if (superclass && superclass->hasTypeParameter ()) {
181
+ superclass = mapTypeIntoContext (superclass,
182
+ builder.getLookupConformanceFn ());
183
+ if (superclass->is <ErrorType>())
184
+ superclass = Type ();
185
+ }
215
186
216
- // Collect the protocol conformances for the archetype.
217
- SmallVector<ProtocolDecl *, 4 > protos;
218
- for (const auto &conforms : equivClass->conformsTo ) {
219
- auto proto = conforms.first ;
187
+ // Collect the protocol conformances for the archetype.
188
+ SmallVector<ProtocolDecl *, 4 > protos;
189
+ for (const auto &conforms : equivClass->conformsTo ) {
190
+ auto proto = conforms.first ;
220
191
221
- if (!equivClass->isConformanceSatisfiedBySuperclass (proto))
222
- protos.push_back (proto);
223
- }
192
+ if (!equivClass->isConformanceSatisfiedBySuperclass (proto))
193
+ protos.push_back (proto);
194
+ }
224
195
225
- ArchetypeType *archetype;
226
- ASTContext &ctx = builder.getASTContext ();
227
- if (parentArchetype) {
228
- // Create a nested archetype.
229
- auto *depMemTy = anchor->castTo <DependentMemberType>();
230
- archetype = NestedArchetypeType::getNew (ctx, parentArchetype, depMemTy,
196
+ if (parentArchetype) {
197
+ auto *depMemTy = anchor->castTo <DependentMemberType>();
198
+ result = NestedArchetypeType::getNew (ctx, parentArchetype, depMemTy,
199
+ protos, superclass,
200
+ equivClass->layout );
201
+ } else {
202
+ result = PrimaryArchetypeType::getNew (ctx, this , genericParam,
231
203
protos, superclass,
232
204
equivClass->layout );
205
+ }
206
+ }
233
207
234
- // Register this archetype with its parent.
235
- parentArchetype->registerNestedType (assocType->getName (), archetype);
208
+ // Cache the new archetype for future lookups.
209
+ if (auto depMemTy = anchor->getAs <DependentMemberType>()) {
210
+ parentArchetype->registerNestedType (depMemTy->getName (), result);
236
211
} else {
237
- // Create a top-level archetype.
238
- auto genericParam = anchor->castTo <GenericTypeParamType>();
239
- archetype = PrimaryArchetypeType::getNew (ctx, this , genericParam,
240
- protos, superclass,
241
- equivClass->layout );
242
-
243
- // Register the archetype with the generic environment.
244
- addMapping (genericParam, archetype);
212
+ addMapping (genericParam, result);
245
213
}
246
214
247
- return archetype ;
215
+ return result ;
248
216
}
249
217
250
218
void ArchetypeType::resolveNestedType (
@@ -258,7 +226,7 @@ void ArchetypeType::resolveNestedType(
258
226
259
227
assert (!nested.second ||
260
228
nested.second ->isEqual (result) ||
261
- ( nested.second ->hasError () && result-> hasError () ));
229
+ nested.second ->is <ErrorType>( ));
262
230
nested.second = result;
263
231
}
264
232
@@ -275,17 +243,18 @@ Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
275
243
return Type ();
276
244
277
245
// If the context type isn't already known, lazily create it.
278
- Type contextType = self->getContextTypes ()[index];
279
- if (!contextType) {
280
- auto mutableSelf = const_cast <GenericEnvironment *>(self);
281
- contextType = mutableSelf->getOrCreateArchetypeFromInterfaceType (type);
282
-
283
- // FIXME: Redundant mapping from key -> index.
284
- if (self->getContextTypes ()[index].isNull ())
285
- mutableSelf->addMapping (key, contextType);
286
- }
246
+ auto mutableSelf = const_cast <GenericEnvironment *>(self);
247
+ Type &contextType = mutableSelf->getContextTypes ()[index];
248
+ if (contextType)
249
+ return contextType;
287
250
288
- return contextType;
251
+ auto result = mutableSelf->getOrCreateArchetypeFromInterfaceType (type);
252
+
253
+ assert (!contextType ||
254
+ contextType->isEqual (result) ||
255
+ contextType->is <ErrorType>());
256
+ contextType = result;
257
+ return result;
289
258
}
290
259
291
260
return Type ();
0 commit comments