@@ -193,23 +193,6 @@ void TypeChecker::forceExternalDeclMembers(NominalTypeDecl *nominalDecl) {
193
193
}
194
194
}
195
195
196
- static Optional<Type>
197
- resolveAssociatedTypeInContext (TypeChecker &TC, AssociatedTypeDecl *assocType,
198
- DeclContext *DC, GenericTypeResolver *resolver) {
199
- auto protoSelf = DC->getProtocolSelf ();
200
- auto selfTy = protoSelf->getDeclaredType ()->castTo <GenericTypeParamType>();
201
- auto baseTy = resolver->resolveGenericTypeParamType (selfTy);
202
-
203
- if (baseTy->isTypeParameter ())
204
- return resolver->resolveSelfAssociatedType (baseTy, DC, assocType);
205
-
206
- if (assocType->getDeclContext () != DC)
207
- return TC.substMemberTypeWithBase (DC->getParentModule (), assocType,
208
- protoSelf->getArchetype (),
209
- /* isTypeReference=*/ true );
210
- return None;
211
- }
212
-
213
196
Type TypeChecker::resolveTypeInContext (
214
197
TypeDecl *typeDecl,
215
198
DeclContext *fromDC,
@@ -239,15 +222,12 @@ Type TypeChecker::resolveTypeInContext(
239
222
nominalType = nullptr ;
240
223
}
241
224
242
- // Walk up through the type scopes to find the context where the type
243
- // declaration was found. When we find it, substitute the appropriate base
244
- // type.
225
+ // Walk up through the type scopes to find the context containing the type
226
+ // being resolved.
245
227
auto ownerDC = typeDecl->getDeclContext ();
246
228
bool nonTypeOwner = !ownerDC->isTypeContext ();
247
229
auto ownerNominal = ownerDC->getAsNominalTypeOrNominalTypeExtensionContext ();
248
230
auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl);
249
- auto alias = dyn_cast<TypeAliasDecl>(typeDecl);
250
- DeclContext *typeParent = nullptr ;
251
231
assert ((ownerNominal || nonTypeOwner) &&
252
232
" Owner must be a nominal type or a non type context" );
253
233
@@ -273,140 +253,126 @@ Type TypeChecker::resolveTypeInContext(
273
253
return typeDecl->getDeclaredType ();
274
254
275
255
// For the next steps we need our parentDC to be a type context
276
- if (!parentDC->isTypeContext ()) {
256
+ if (!parentDC->isTypeContext ())
277
257
continue ;
278
- } else if (!typeParent) {
279
- // Remember the first type decl context in the hierarchy for later use
280
- typeParent = parentDC;
281
- }
282
-
283
- // If we found an associated type in an inherited protocol, the base for our
284
- // reference to this associated type is our own `Self`. If we can't resolve
285
- // the associated type during this iteration, try again on the next.
286
- if (assocType) {
287
- if ( auto proto = parentDC-> getAsProtocolOrProtocolExtensionContext ()) {
288
- auto assocProto = assocType-> getProtocol ();
289
- if (proto == assocProto || proto-> inheritsFrom (assocProto)) {
290
- // If the associated type is from our own protocol or we inherit from
291
- // the associated type's protocol, resolve it
292
- if ( auto resolved = resolveAssociatedTypeInContext (
293
- * this , assocType, parentDC, resolver))
294
- return *resolved ;
295
-
296
- } else if (auto ED = dyn_cast<ExtensionDecl>(parentDC )) {
297
- // Otherwise, if we are in an extension there might be other
298
- // associated types brought into the context through
299
- // `extension ... where Self : SomeProtocol`
300
- for ( auto req : ED-> getGenericParams ()-> getTrailingRequirements ()) {
301
- // Reject requirements other than constraints with an subject other
302
- // than `Self`
303
- if ( req.getKind () != RequirementReprKind::TypeConstraint ||
304
- !req.getSubject ()->castTo <ArchetypeType>()->isSelfDerived ())
258
+
259
+ // Search the type of this context and its supertypes (if its a
260
+ // class) or refined protocols (if its a protocol).
261
+ llvm::SmallPtrSet< const NominalTypeDecl *, 8 > visited;
262
+ llvm::SmallVector<Type, 8 > stack;
263
+
264
+ // Start with the type of the current context.
265
+ if ( auto fromType = resolver-> resolveTypeOfContext (parentDC))
266
+ stack. push_back (fromType);
267
+
268
+ // If we are in a protocol extension there might be other type aliases and
269
+ // nominal types brought into the context through requirements on Self,
270
+ // for example:
271
+ //
272
+ // extension MyProtocol where Self : YourProtocol { ... }
273
+ if ( parentDC-> getAsProtocolExtensionContext ()) {
274
+ auto ED = cast<ExtensionDecl>(parentDC) ;
275
+ if ( auto genericParams = ED-> getGenericParams ()) {
276
+ for (auto req : genericParams-> getTrailingRequirements ( )) {
277
+ // We might be resolving 'req.getSubject()' itself.
278
+ // This whole case feels like a hack -- there should be a
279
+ // more principled way to represent extensions of protocol
280
+ // compositions.
281
+ if (req. getKind () == RequirementReprKind::TypeConstraint) {
282
+ if (!req. getSubject () ||
283
+ ! req.getSubject ()-> is <ArchetypeType>() ||
284
+ !req.getSubject ()->castTo <ArchetypeType>()->getSelfProtocol ())
305
285
continue ;
306
286
307
- // If the associated type is defined in the same protocol which is
308
- // required for this extension, or if the required protocol inherits
309
- // from the protocol the associated type is declared in, we can
310
- // resolve the associated type with our `Self` as the reference
311
- // point.
312
- auto reqProto =
313
- req.getConstraint ()->castTo <ProtocolType>()->getDecl ();
314
- if (reqProto == assocProto || reqProto->inheritsFrom (assocProto)) {
315
- if (auto resolved = resolveAssociatedTypeInContext (
316
- *this , assocType, parentDC, resolver))
317
- return *resolved;
318
- break ;
319
- }
287
+ stack.push_back (req.getConstraint ());
320
288
}
321
289
}
322
290
}
323
291
}
324
-
325
- // If we found an alias type in an inherited protocol, resolve it based on our
326
- // own `Self`.
327
- if (alias && alias->hasInterfaceType ()) {
328
- auto metaType = alias->getInterfaceType ()->getAs <MetatypeType>();
329
- auto memberType = metaType ? metaType->getInstanceType ()->getAs <DependentMemberType>() :
330
- nullptr ;
331
-
332
- if (memberType && parentDC->getAsProtocolOrProtocolExtensionContext ()) {
333
- auto protoSelf = parentDC->getProtocolSelf ();
334
- auto selfTy = protoSelf->getDeclaredType ()->castTo <GenericTypeParamType>();
335
- auto baseTy = resolver->resolveGenericTypeParamType (selfTy);
336
-
337
- SmallVector<DependentMemberType *, 4 > memberTypes;
338
- do {
339
- memberTypes.push_back (memberType);
340
- memberType = memberType->getBase ()->getAs <DependentMemberType>();
341
- } while (memberType);
342
-
343
- auto module = parentDC->getParentModule ();
344
- while (memberTypes.size ()) {
345
- baseTy = memberTypes.back ()->substBaseType (module , baseTy, nullptr );
346
- memberTypes.pop_back ();
347
- }
348
- return baseTy;
349
- }
350
- }
351
292
352
- // Search the type of this context and its supertypes.
353
- llvm::SmallPtrSet<const NominalTypeDecl *, 8 > visited;
354
- for (auto fromType = resolver->resolveTypeOfContext (parentDC);
355
- fromType;
356
- fromType = getSuperClassOf (fromType)) {
293
+ while (!stack.empty ()) {
294
+ auto fromType = stack.back ();
295
+ auto *fromProto = parentDC->getAsProtocolOrProtocolExtensionContext ();
296
+
297
+ stack.pop_back ();
298
+
357
299
// If we hit circularity, we will diagnose at some point in typeCheckDecl().
358
300
// However we have to explicitly guard against that here because we get
359
301
// called as part of validateDecl().
360
302
if (!visited.insert (fromType->getAnyNominal ()).second )
361
- break ;
303
+ continue ;
304
+
305
+ // Handle this case:
306
+ // - Current context: concrete type
307
+ // - Nested type: associated type
308
+ // - Nested type's context: protocol or protocol extension
309
+ //
310
+ if (assocType && fromProto == nullptr ) {
311
+ ProtocolConformance *conformance = nullptr ;
312
+
313
+ // If the conformance check failed, the associated type is for a
314
+ // conformance of an outer context.
315
+ if (!options.contains (TR_InheritanceClause) &&
316
+ conformsToProtocol (fromType,
317
+ cast<ProtocolDecl>(ownerNominal),
318
+ parentDC, ConformanceCheckFlags::Used,
319
+ &conformance) &&
320
+ conformance) {
321
+ return conformance->getTypeWitness (assocType, this ).getReplacement ();
322
+ }
323
+ }
362
324
363
- // If the nominal type declaration of the context type we're looking at
364
- // matches the owner's nominal type declaration, this is how we found
365
- // the member type declaration. Substitute the type we're coming from as
366
- // the base of the member type to produce the projected type result.
325
+ // Handle these cases:
326
+ // - Current context: concrete type
327
+ // - Nested type: concrete type or type alias
328
+ // - Nested type's context: concrete type
329
+ //
330
+ // - Current context: protocol or protocol extension
331
+ // - Nested type: type alias
332
+ // - Nested type's context: protocol or protocol extension
333
+ //
334
+ // Note: this is not supported yet, FIXME:
335
+ // - Current context: concrete type
336
+ // - Nested type: type alias
337
+ // - Nested type's context: protocol or protocol extension
338
+ //
367
339
if (fromType->getAnyNominal () == ownerNominal) {
368
- // If we are referring into a protocol or extension thereof,
369
- // the base type is the 'Self'.
370
- if (ownerDC->getAsProtocolOrProtocolExtensionContext ()) {
371
- auto selfTy = ownerDC->getProtocolSelf ()->getDeclaredType ()
372
- ->castTo <GenericTypeParamType>();
373
- fromType = resolver->resolveGenericTypeParamType (selfTy);
340
+ if (fromProto &&
341
+ ownerNominal->getAsProtocolOrProtocolExtensionContext ()) {
342
+ // If we are looking up an associated type or a protocol's type alias
343
+ // from a protocol or protocol extension, use the archetype for 'Self'
344
+ // instead of the existential type.
345
+ assert (fromType->is <ProtocolType>());
346
+
347
+ auto protoSelf = parentDC->getProtocolSelf ();
348
+ auto selfType = protoSelf
349
+ ->getDeclaredType ()
350
+ ->castTo <GenericTypeParamType>();
351
+ fromType = resolver->resolveGenericTypeParamType (selfType);
352
+
353
+ if (assocType) {
354
+ // Odd special case, ask Doug to explain it over pizza one day
355
+ if (fromType->isTypeParameter ())
356
+ return resolver->resolveSelfAssociatedType (
357
+ fromType, parentDC, assocType);
358
+ }
374
359
}
375
360
376
- // Perform the substitution.
377
361
return substMemberTypeWithBase (parentDC->getParentModule (), typeDecl,
378
362
fromType, /* isTypeReference=*/ true );
379
363
}
380
364
381
- ProtocolConformance *conformance = nullptr ;
382
- if (assocType &&
383
- !options.contains (TR_InheritanceClause) &&
384
- conformsToProtocol (fromType,
385
- cast<ProtocolDecl>(assocType->getDeclContext ()),
386
- parentDC, ConformanceCheckFlags::Used,
387
- &conformance) &&
388
- conformance) {
389
- return conformance->getTypeWitness (assocType, this ).getReplacement ();
365
+ if (auto superclassTy = getSuperClassOf (fromType))
366
+ stack.push_back (superclassTy);
367
+ else if (auto protoTy = fromType->getAs <ProtocolType>()) {
368
+ for (auto *proto : protoTy->getDecl ()->getInheritedProtocols (this ))
369
+ if (auto refinedTy = proto->getDeclaredTypeInContext ())
370
+ stack.push_back (refinedTy);
390
371
}
391
372
}
392
373
}
393
374
394
- // At this point by iterating through the decl context hierarchy we should
395
- // have encountered the first type context in the stack.
396
- assert (typeParent && " incomplete iteration" );
397
- assert (!typeParent->isModuleContext ());
398
-
399
- // Substitute in the appropriate type for 'Self'.
400
- // FIXME: We shouldn't have to guess here; the caller should tell us.
401
- Type fromType;
402
- if (typeParent->getAsProtocolOrProtocolExtensionContext ())
403
- fromType = typeParent->getProtocolSelf ()->getArchetype ();
404
- else
405
- fromType = resolver->resolveTypeOfContext (typeParent);
406
-
407
- // Perform the substitution.
408
- return substMemberTypeWithBase (typeParent->getParentModule (), typeDecl,
409
- fromType, /* isTypeReference=*/ true );
375
+ llvm_unreachable (" Cannot resolve type" );
410
376
}
411
377
412
378
Type TypeChecker::applyGenericArguments (Type type, SourceLoc loc,
@@ -537,7 +503,8 @@ Type TypeChecker::applyUnboundGenericArguments(
537
503
538
504
// Check the generic arguments against the generic signature.
539
505
auto genericSig = unbound->getDecl ()->getGenericSignature ();
540
- if (unbound->getDecl ()->isValidatingGenericSignature ()) {
506
+ if (!unbound->getDecl ()->hasType () ||
507
+ unbound->getDecl ()->isValidatingGenericSignature ()) {
541
508
diagnose (loc, diag::recursive_requirement_reference);
542
509
return nullptr ;
543
510
}
@@ -2474,7 +2441,6 @@ Type TypeChecker::substMemberTypeWithBase(Module *module,
2474
2441
Type memberType = isTypeReference
2475
2442
? cast<TypeDecl>(member)->getDeclaredInterfaceType ()
2476
2443
: member->getInterfaceType ();
2477
-
2478
2444
if (isTypeReference) {
2479
2445
// The declared interface type for a generic type will have the type
2480
2446
// arguments; strip them off.
0 commit comments