@@ -397,13 +397,22 @@ void NormalProtocolConformance::setTypeWitness(
397
397
TypeWitnesses[assocType] = std::make_pair (substitution, typeDecl);
398
398
}
399
399
400
- Type NormalProtocolConformance ::getAssociatedType (Type assocType,
401
- LazyResolver *resolver) const {
400
+ Type ProtocolConformance ::getAssociatedType (Type assocType,
401
+ LazyResolver *resolver) const {
402
402
assert (assocType->isTypeParameter () &&
403
403
" associated type must be a type parameter" );
404
404
405
+ ProtocolConformanceRef ref (const_cast <ProtocolConformance*>(this ));
406
+ return ref.getAssociatedType (getType (), assocType, resolver);
407
+ }
408
+
409
+ Type ProtocolConformanceRef::getAssociatedType (Type conformingType,
410
+ Type assocType,
411
+ LazyResolver *resolver) const {
412
+ assert (!isConcrete () || getConcrete ()->getType ()->isEqual (conformingType));
413
+
405
414
auto type = assocType->getCanonicalType ();
406
- auto proto = getProtocol ();
415
+ auto proto = getRequirement ();
407
416
408
417
#if false
409
418
// Fast path for generic parameters.
@@ -421,13 +430,43 @@ Type NormalProtocolConformance::getAssociatedType(Type assocType,
421
430
#endif
422
431
423
432
// General case: consult the substitution map.
424
- auto self = const_cast <NormalProtocolConformance *>(this );
425
433
auto substMap =
426
- SubstitutionMap::getProtocolSubstitutions (proto, getType (),
427
- ProtocolConformanceRef (self));
434
+ SubstitutionMap::getProtocolSubstitutions (proto, conformingType, *this );
428
435
return type.subst (substMap);
429
436
}
430
437
438
+ ProtocolConformanceRef
439
+ ProtocolConformanceRef::getAssociatedConformance (Type conformingType,
440
+ Type assocType,
441
+ ProtocolDecl *protocol,
442
+ LazyResolver *resolver) const {
443
+ // If this is a concrete conformance, look up the associated conformance.
444
+ if (isConcrete ()) {
445
+ auto conformance = getConcrete ();
446
+ assert (conformance->getType ()->isEqual (conformingType));
447
+ return conformance->getAssociatedConformance (assocType, protocol, resolver);
448
+ }
449
+
450
+ // Otherwise, apply the substitution {self -> conformingType}
451
+ // to the abstract conformance requirement laid upon the dependent type
452
+ // by the protocol.
453
+ auto subMap =
454
+ SubstitutionMap::getProtocolSubstitutions (getRequirement (),
455
+ conformingType, *this );
456
+ auto abstractConf = ProtocolConformanceRef (protocol);
457
+ return abstractConf.subst (assocType,
458
+ QuerySubstitutionMap{subMap},
459
+ LookUpConformanceInSubstitutionMap (subMap));
460
+ }
461
+
462
+ ProtocolConformanceRef
463
+ ProtocolConformance::getAssociatedConformance (Type assocType,
464
+ ProtocolDecl *protocol,
465
+ LazyResolver *resolver) const {
466
+ CONFORMANCE_SUBCLASS_DISPATCH (getAssociatedConformance,
467
+ (assocType, protocol, resolver))
468
+ }
469
+
431
470
ProtocolConformanceRef
432
471
NormalProtocolConformance::getAssociatedConformance (Type assocType,
433
472
ProtocolDecl *protocol,
@@ -582,6 +621,35 @@ SpecializedProtocolConformance::getWitness(ValueDecl *requirement,
582
621
return GenericConformance->getWitness (requirement, resolver);
583
622
}
584
623
624
+ ProtocolConformanceRef
625
+ SpecializedProtocolConformance::getAssociatedConformance (Type assocType,
626
+ ProtocolDecl *protocol,
627
+ LazyResolver *resolver) const {
628
+ ProtocolConformanceRef conformance =
629
+ GenericConformance->getAssociatedConformance (assocType, protocol, resolver);
630
+
631
+ auto genericEnv = GenericConformance->getGenericEnvironment ();
632
+ auto subMap = genericEnv->getSubstitutionMap (GenericSubstitutions);
633
+
634
+ Type origType =
635
+ (conformance.isConcrete ()
636
+ ? conformance.getConcrete ()->getType ()
637
+ : GenericConformance->getAssociatedType (assocType, resolver));
638
+
639
+ return conformance.subst (origType,
640
+ QuerySubstitutionMap{subMap},
641
+ LookUpConformanceInSubstitutionMap (subMap));
642
+ }
643
+
644
+ ProtocolConformanceRef
645
+ InheritedProtocolConformance::getAssociatedConformance (Type assocType,
646
+ ProtocolDecl *protocol,
647
+ LazyResolver *resolver) const {
648
+ // FIXME: Substitute!
649
+ return InheritedConformance->getAssociatedConformance (assocType, protocol,
650
+ resolver);
651
+ }
652
+
585
653
const NormalProtocolConformance *
586
654
ProtocolConformance::getRootNormalConformance () const {
587
655
const ProtocolConformance *C = this ;
0 commit comments