18
18
#include " swift/AST/ASTContext.h"
19
19
#include " swift/AST/GenericSignatureBuilder.h"
20
20
#include " swift/AST/ProtocolConformance.h"
21
+ #include " swift/Basic/Defer.h"
22
+ #include " GenericSignatureBuilderImpl.h"
21
23
22
24
using namespace swift ;
23
25
@@ -46,15 +48,24 @@ GenericEnvironment::getGenericParams() const {
46
48
return Signature->getGenericParams ();
47
49
}
48
50
49
- GenericEnvironment::GenericEnvironment (GenericSignature signature,
50
- GenericSignatureBuilder *builder)
51
- : Signature(signature), Builder(builder)
51
+ GenericEnvironment::GenericEnvironment (GenericSignature signature)
52
+ : Signature(signature)
52
53
{
53
54
// Clear out the memory that holds the context types.
54
55
std::uninitialized_fill (getContextTypes ().begin (), getContextTypes ().end (),
55
56
Type ());
56
57
}
57
58
59
+ GenericSignatureBuilder *GenericEnvironment::getGenericSignatureBuilder () const {
60
+ if (Builder)
61
+ return Builder;
62
+
63
+ const_cast <GenericEnvironment *>(this )->Builder
64
+ = Signature->getGenericSignatureBuilder ();
65
+
66
+ return Builder;
67
+ }
68
+
58
69
void GenericEnvironment::addMapping (GenericParamKey key,
59
70
Type contextType) {
60
71
// Find the index into the parallel arrays of generic parameters and
@@ -64,7 +75,9 @@ void GenericEnvironment::addMapping(GenericParamKey key,
64
75
assert (genericParams[index] == key && " Bad generic parameter" );
65
76
66
77
// Add the mapping from the generic parameter to the context type.
67
- assert (getContextTypes ()[index].isNull () && " Already recoded this mapping" );
78
+ assert (getContextTypes ()[index].isNull () ||
79
+ getContextTypes ()[index]->is <ErrorType>() &&
80
+ " Already recoded this mapping" );
68
81
getContextTypes ()[index] = contextType;
69
82
}
70
83
@@ -107,6 +120,116 @@ Type TypeBase::mapTypeOutOfContext() {
107
120
SubstFlags::AllowLoweredTypes);
108
121
}
109
122
123
+ Type
124
+ GenericEnvironment::getOrCreateArchetypeFromInterfaceType (Type depType) {
125
+ auto &builder = *getGenericSignatureBuilder ();
126
+ auto &ctx = builder.getASTContext ();
127
+
128
+ auto resolved =
129
+ builder.maybeResolveEquivalenceClass (
130
+ depType,
131
+ ArchetypeResolutionKind::CompleteWellFormed,
132
+ /* wantExactPotentialArchetype=*/ false );
133
+ if (!resolved)
134
+ return ErrorType::get (depType);
135
+
136
+ if (auto concrete = resolved.getAsConcreteType ()) {
137
+ return mapTypeIntoContext (concrete,
138
+ builder.getLookupConformanceFn ());
139
+ }
140
+
141
+ auto *equivClass = resolved.getEquivalenceClass (builder);
142
+
143
+ auto genericParams = getGenericParams ();
144
+ Type anchor = equivClass->getAnchor (builder, genericParams);
145
+
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>>).
149
+ ArchetypeType *parentArchetype = nullptr ;
150
+ GenericTypeParamType *genericParam = nullptr ;
151
+ if (auto depMemTy = anchor->getAs <DependentMemberType>()) {
152
+ parentArchetype =
153
+ getOrCreateArchetypeFromInterfaceType (depMemTy->getBase ())
154
+ ->getAs <ArchetypeType>();
155
+ if (!parentArchetype)
156
+ return ErrorType::get (depMemTy);
157
+
158
+ auto name = depMemTy->getName ();
159
+ if (auto type = parentArchetype->getNestedTypeIfKnown (name))
160
+ return *type;
161
+
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));
168
+ }
169
+
170
+ Type result;
171
+
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
+ }
186
+
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 ;
191
+
192
+ if (!equivClass->isConformanceSatisfiedBySuperclass (proto))
193
+ protos.push_back (proto);
194
+ }
195
+
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,
203
+ protos, superclass,
204
+ equivClass->layout );
205
+ }
206
+ }
207
+
208
+ // Cache the new archetype for future lookups.
209
+ if (auto depMemTy = anchor->getAs <DependentMemberType>()) {
210
+ parentArchetype->registerNestedType (depMemTy->getName (), result);
211
+ } else {
212
+ addMapping (genericParam, result);
213
+ }
214
+
215
+ return result;
216
+ }
217
+
218
+ void ArchetypeType::resolveNestedType (
219
+ std::pair<Identifier, Type> &nested) const {
220
+ Type interfaceType = getInterfaceType ();
221
+ Type memberInterfaceType =
222
+ DependentMemberType::get (interfaceType, nested.first );
223
+
224
+ Type result = getGenericEnvironment ()->getOrCreateArchetypeFromInterfaceType (
225
+ memberInterfaceType);
226
+
227
+ assert (!nested.second ||
228
+ nested.second ->isEqual (result) ||
229
+ nested.second ->is <ErrorType>());
230
+ nested.second = result;
231
+ }
232
+
110
233
Type QueryInterfaceTypeSubstitutions::operator ()(SubstitutableType *type) const {
111
234
if (auto gp = type->getAs <GenericTypeParamType>()) {
112
235
// Find the index into the parallel arrays of generic parameters and
@@ -120,24 +243,18 @@ Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
120
243
return Type ();
121
244
122
245
// If the context type isn't already known, lazily create it.
123
- Type contextType = self->getContextTypes ()[index];
124
- if (!contextType) {
125
- assert (self->Builder &&" Missing generic signature builder for lazy query" );
126
- auto equivClass =
127
- self->Builder ->resolveEquivalenceClass (
128
- type,
129
- ArchetypeResolutionKind::CompleteWellFormed);
130
-
131
- auto mutableSelf = const_cast <GenericEnvironment *>(self);
132
- contextType = equivClass->getTypeInContext (*mutableSelf->Builder ,
133
- mutableSelf);
134
-
135
- // FIXME: Redundant mapping from key -> index.
136
- if (self->getContextTypes ()[index].isNull ())
137
- mutableSelf->addMapping (key, contextType);
138
- }
139
-
140
- return contextType;
246
+ auto mutableSelf = const_cast <GenericEnvironment *>(self);
247
+ Type &contextType = mutableSelf->getContextTypes ()[index];
248
+ if (contextType)
249
+ return contextType;
250
+
251
+ auto result = mutableSelf->getOrCreateArchetypeFromInterfaceType (type);
252
+
253
+ assert (!contextType ||
254
+ contextType->isEqual (result) ||
255
+ contextType->is <ErrorType>());
256
+ contextType = result;
257
+ return result;
141
258
}
142
259
143
260
return Type ();
0 commit comments