@@ -253,6 +253,82 @@ void ArchetypeBuilder::PotentialArchetype::resolveAssociatedType(
253
253
--builder.Impl ->NumUnresolvedNestedTypes ;
254
254
}
255
255
256
+ // / Retrieve the conformance for the superclass constraint of the given
257
+ // / potential archetype (if present) to the given protocol.
258
+ // /
259
+ // / \param pa The potential archetype whose superclass constraint is being
260
+ // / queried.
261
+ // /
262
+ // / \param proto The protocol to which we are establisting conformance.
263
+ // /
264
+ // / \param cache A cache of the result, so we don't perform this query
265
+ // / multiple times.
266
+ // /
267
+ // / \param builder The archetype builder in which the potential archetype
268
+ // / resides.
269
+ static ProtocolConformance *getSuperConformance (
270
+ ArchetypeBuilder::PotentialArchetype *pa,
271
+ ProtocolDecl *proto,
272
+ Optional<ProtocolConformance *> &cache,
273
+ ArchetypeBuilder &builder) {
274
+ // If we cached a result already, return it.
275
+ if (cache) return *cache;
276
+
277
+ // Get the superclass constraint.
278
+ Type superclass = pa->getSuperclass ();
279
+ if (!superclass) {
280
+ cache = nullptr ;
281
+ return nullptr ;
282
+ }
283
+
284
+ // Lookup the conformance of the superclass to this protocol.
285
+ auto conformance =
286
+ builder.getModule ().lookupConformance (superclass, proto,
287
+ builder.getLazyResolver ());
288
+ switch (conformance.getInt ()) {
289
+ case ConformanceKind::Conforms:
290
+ cache = conformance.getPointer ();
291
+ return conformance.getPointer ();
292
+
293
+ case ConformanceKind::DoesNotConform:
294
+ case ConformanceKind::UncheckedConforms:
295
+ cache = nullptr ;
296
+ return nullptr ;
297
+ }
298
+ }
299
+
300
+ // / If there is a same-type requirement to be added for the given nested type
301
+ // / due to a superclass constraint on the parent type, add it now.
302
+ static void maybeAddSameTypeRequirementForNestedType (
303
+ ArchetypeBuilder::PotentialArchetype *parentPA,
304
+ ArchetypeBuilder::PotentialArchetype *nestedPA,
305
+ RequirementSource fromSource,
306
+ Optional<ProtocolConformance *> &cache,
307
+ ArchetypeBuilder &builder) {
308
+ auto assocType = nestedPA->getResolvedAssociatedType ();
309
+ assert (assocType && " Not resolved to an associated type?" );
310
+
311
+ // Find the superclass conformance.
312
+ auto proto = assocType->getProtocol ();
313
+ auto conformance = getSuperConformance (parentPA, proto, cache, builder);
314
+ if (!conformance) return ;
315
+
316
+ // Dig out the type witness.
317
+ auto concreteType = conformance->getTypeWitness (assocType,
318
+ builder.getLazyResolver ())
319
+ .getReplacement ();
320
+ if (!concreteType) return ;
321
+
322
+ // Add the same-type constraint.
323
+ RequirementSource source (RequirementSource::Protocol, fromSource.getLoc ());
324
+ concreteType = ArchetypeBuilder::mapTypeOutOfContext (
325
+ conformance->getDeclContext (), concreteType);
326
+ if (auto otherPA = builder.resolveArchetype (concreteType))
327
+ builder.addSameTypeRequirementBetweenArchetypes (nestedPA, otherPA, source);
328
+ else
329
+ builder.addSameTypeRequirementToConcrete (nestedPA, concreteType, source);
330
+ }
331
+
256
332
bool ArchetypeBuilder::PotentialArchetype::addConformance (
257
333
ProtocolDecl *proto,
258
334
const RequirementSource &source,
@@ -275,6 +351,7 @@ bool ArchetypeBuilder::PotentialArchetype::addConformance(
275
351
276
352
// Check whether any associated types in this protocol resolve
277
353
// nested types of this potential archetype.
354
+ Optional<ProtocolConformance *> cachedSuperConformance;
278
355
for (auto member : proto->getMembers ()) {
279
356
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
280
357
if (!assocType)
@@ -287,6 +364,13 @@ bool ArchetypeBuilder::PotentialArchetype::addConformance(
287
364
// If the nested type was not already resolved, do so now.
288
365
if (!known->second .front ()->getResolvedAssociatedType ()) {
289
366
known->second .front ()->resolveAssociatedType (assocType, builder);
367
+
368
+ // If there's a superclass constraint that conforms to the protocol,
369
+ // add the appropriate same-type relationship.
370
+ maybeAddSameTypeRequirementForNestedType (this , known->second .front (),
371
+ source,
372
+ cachedSuperConformance,
373
+ builder);
290
374
continue ;
291
375
}
292
376
@@ -299,6 +383,13 @@ bool ArchetypeBuilder::PotentialArchetype::addConformance(
299
383
otherPA->SameTypeSource = RequirementSource (RequirementSource::Inferred,
300
384
source.getLoc ());
301
385
known->second .push_back (otherPA);
386
+
387
+ // If there's a superclass constraint that conforms to the protocol,
388
+ // add the appropriate same-type relationship.
389
+ maybeAddSameTypeRequirementForNestedType (this , otherPA,
390
+ source,
391
+ cachedSuperConformance,
392
+ builder);
302
393
}
303
394
304
395
return true ;
@@ -367,8 +458,8 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
367
458
if (Representative != this )
368
459
return getRepresentative ()->getNestedType (nestedName, builder);
369
460
461
+ // If we already have a nested type with this name, return it.
370
462
llvm::TinyPtrVector<PotentialArchetype *> &nested = NestedTypes[nestedName];
371
-
372
463
if (!nested.empty ()) {
373
464
return nested.front ();
374
465
}
@@ -377,6 +468,8 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
377
468
// of one of the protocols to which the parent potential
378
469
// archetype conforms.
379
470
for (const auto &conforms : ConformsTo) {
471
+ Optional<ProtocolConformance *> cachedSuperConformance;
472
+
380
473
for (auto member : conforms.first ->lookupDirect (nestedName)) {
381
474
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
382
475
if (!assocType)
@@ -387,15 +480,21 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
387
480
388
481
// If we have resolved this nested type to more than one associated
389
482
// type, create same-type constraints between them.
483
+ RequirementSource source (RequirementSource::Inferred, SourceLoc ());
390
484
if (!nested.empty ()) {
391
485
pa->Representative = nested.front ()->getRepresentative ();
392
486
pa->Representative ->EquivalenceClass .push_back (pa);
393
- pa->SameTypeSource = RequirementSource (RequirementSource::Inferred,
394
- SourceLoc ());
487
+ pa->SameTypeSource = source;
395
488
}
396
489
397
490
// Add this resolved nested type.
398
491
nested.push_back (pa);
492
+
493
+ // If there's a superclass constraint that conforms to the protocol,
494
+ // add the appropriate same-type relationship.
495
+ maybeAddSameTypeRequirementForNestedType (this , pa, source,
496
+ cachedSuperConformance,
497
+ builder);
399
498
}
400
499
}
401
500
@@ -876,6 +975,18 @@ bool ArchetypeBuilder::addSuperclassRequirement(PotentialArchetype *T,
876
975
T->Superclass = Superclass;
877
976
T->SuperclassSource = Source;
878
977
978
+ // Resolve any nested types via the superclass.
979
+ for (auto &nested : T->getNestedTypes ()) {
980
+ Optional<ProtocolConformance *> superclassConformance;
981
+ for (auto nestedPA : nested.second ) {
982
+ if (nestedPA->getResolvedAssociatedType ()) {
983
+ maybeAddSameTypeRequirementForNestedType (T, nested.second .front (),
984
+ Source,
985
+ superclassConformance, *this );
986
+ }
987
+ }
988
+ }
989
+
879
990
return false ;
880
991
}
881
992
0 commit comments