@@ -193,6 +193,23 @@ 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
+
196
213
Type TypeChecker::resolveTypeInContext (
197
214
TypeDecl *typeDecl,
198
215
DeclContext *fromDC,
@@ -222,12 +239,15 @@ Type TypeChecker::resolveTypeInContext(
222
239
nominalType = nullptr ;
223
240
}
224
241
225
- // Walk up through the type scopes to find the context containing the type
226
- // being resolved.
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.
227
245
auto ownerDC = typeDecl->getDeclContext ();
228
246
bool nonTypeOwner = !ownerDC->isTypeContext ();
229
247
auto ownerNominal = ownerDC->getAsNominalTypeOrNominalTypeExtensionContext ();
230
248
auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl);
249
+ auto alias = dyn_cast<TypeAliasDecl>(typeDecl);
250
+ DeclContext *typeParent = nullptr ;
231
251
assert ((ownerNominal || nonTypeOwner) &&
232
252
" Owner must be a nominal type or a non type context" );
233
253
@@ -253,126 +273,140 @@ Type TypeChecker::resolveTypeInContext(
253
273
return typeDecl->getDeclaredType ();
254
274
255
275
// For the next steps we need our parentDC to be a type context
256
- if (!parentDC->isTypeContext ())
276
+ if (!parentDC->isTypeContext ()) {
257
277
continue ;
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 ())
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 ())
285
305
continue ;
286
306
287
- stack.push_back (req.getConstraint ());
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
+ }
288
320
}
289
321
}
290
322
}
291
323
}
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
+ }
292
351
293
- while (!stack.empty ()) {
294
- auto fromType = stack.back ();
295
- auto *fromProto = parentDC->getAsProtocolOrProtocolExtensionContext ();
296
-
297
- stack.pop_back ();
298
-
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)) {
299
357
// If we hit circularity, we will diagnose at some point in typeCheckDecl().
300
358
// However we have to explicitly guard against that here because we get
301
359
// called as part of validateDecl().
302
360
if (!visited.insert (fromType->getAnyNominal ()).second )
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
- }
361
+ break ;
324
362
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
- //
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.
339
367
if (fromType->getAnyNominal () == ownerNominal) {
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
- }
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);
359
374
}
360
375
376
+ // Perform the substitution.
361
377
return substMemberTypeWithBase (parentDC->getParentModule (), typeDecl,
362
378
fromType, /* isTypeReference=*/ true );
363
379
}
364
380
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);
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 ();
371
390
}
372
391
}
373
392
}
374
393
375
- llvm_unreachable (" Cannot resolve type" );
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 );
376
410
}
377
411
378
412
Type TypeChecker::applyGenericArguments (Type type, SourceLoc loc,
@@ -503,8 +537,7 @@ Type TypeChecker::applyUnboundGenericArguments(
503
537
504
538
// Check the generic arguments against the generic signature.
505
539
auto genericSig = unbound->getDecl ()->getGenericSignature ();
506
- if (!unbound->getDecl ()->hasType () ||
507
- unbound->getDecl ()->isValidatingGenericSignature ()) {
540
+ if (unbound->getDecl ()->isValidatingGenericSignature ()) {
508
541
diagnose (loc, diag::recursive_requirement_reference);
509
542
return nullptr ;
510
543
}
@@ -2441,6 +2474,7 @@ Type TypeChecker::substMemberTypeWithBase(Module *module,
2441
2474
Type memberType = isTypeReference
2442
2475
? cast<TypeDecl>(member)->getDeclaredInterfaceType ()
2443
2476
: member->getInterfaceType ();
2477
+
2444
2478
if (isTypeReference) {
2445
2479
// The declared interface type for a generic type will have the type
2446
2480
// arguments; strip them off.
0 commit comments