@@ -75,7 +75,9 @@ void GenericEnvironment::addMapping(GenericParamKey key,
7575 assert (genericParams[index] == key && " Bad generic parameter" );
7676
7777 // 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" );
7981 getContextTypes ()[index] = contextType;
8082}
8183
@@ -121,6 +123,8 @@ Type TypeBase::mapTypeOutOfContext() {
121123Type
122124GenericEnvironment::getOrCreateArchetypeFromInterfaceType (Type depType) {
123125 auto &builder = *getGenericSignatureBuilder ();
126+ auto &ctx = builder.getASTContext ();
127+
124128 auto resolved =
125129 builder.maybeResolveEquivalenceClass (
126130 depType,
@@ -129,122 +133,86 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
129133 if (!resolved)
130134 return ErrorType::get (depType);
131135
132- if (auto concrete = resolved.getAsConcreteType ())
133- return concrete;
136+ if (auto concrete = resolved.getAsConcreteType ()) {
137+ return mapTypeIntoContext (concrete,
138+ builder.getLookupConformanceFn ());
139+ }
134140
135141 auto *equivClass = resolved.getEquivalenceClass (builder);
136142
137143 auto genericParams = getGenericParams ();
138144 Type anchor = equivClass->getAnchor (builder, genericParams);
139145
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>>).
171149 ArchetypeType *parentArchetype = nullptr ;
150+ GenericTypeParamType *genericParam = nullptr ;
172151 if (auto depMemTy = anchor->getAs <DependentMemberType>()) {
173- // Map the parent type into this context.
174152 parentArchetype =
175153 getOrCreateArchetypeFromInterfaceType (depMemTy->getBase ())
176154 ->getAs <ArchetypeType>();
177155 if (!parentArchetype)
178156 return ErrorType::get (depMemTy);
179157
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;
186161
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));
191168 }
192169
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;
213171
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+ }
215186
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 ;
220191
221- if (!equivClass->isConformanceSatisfiedBySuperclass (proto))
222- protos.push_back (proto);
223- }
192+ if (!equivClass->isConformanceSatisfiedBySuperclass (proto))
193+ protos.push_back (proto);
194+ }
224195
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,
231203 protos, superclass,
232204 equivClass->layout );
205+ }
206+ }
233207
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);
236211 } 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);
245213 }
246214
247- return archetype ;
215+ return result ;
248216}
249217
250218void ArchetypeType::resolveNestedType (
@@ -258,7 +226,7 @@ void ArchetypeType::resolveNestedType(
258226
259227 assert (!nested.second ||
260228 nested.second ->isEqual (result) ||
261- ( nested.second ->hasError () && result-> hasError () ));
229+ nested.second ->is <ErrorType>( ));
262230 nested.second = result;
263231}
264232
@@ -275,17 +243,18 @@ Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
275243 return Type ();
276244
277245 // 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;
287250
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;
289258 }
290259
291260 return Type ();
0 commit comments