@@ -215,13 +215,16 @@ ProtocolConformance::hasTypeWitness(AssociatedTypeDecl *assocType,
215
215
216
216
std::pair<Type, TypeDecl *>
217
217
ProtocolConformance::getTypeWitnessAndDecl (AssociatedTypeDecl *assocType,
218
- LazyResolver *resolver) const {
219
- CONFORMANCE_SUBCLASS_DISPATCH (getTypeWitnessAndDecl, (assocType, resolver))
218
+ LazyResolver *resolver,
219
+ SubstOptions options) const {
220
+ CONFORMANCE_SUBCLASS_DISPATCH (getTypeWitnessAndDecl,
221
+ (assocType, resolver, options))
220
222
}
221
223
222
224
Type ProtocolConformance::getTypeWitness (AssociatedTypeDecl *assocType,
223
- LazyResolver *resolver) const {
224
- return getTypeWitnessAndDecl (assocType, resolver).first ;
225
+ LazyResolver *resolver,
226
+ SubstOptions options) const {
227
+ return getTypeWitnessAndDecl (assocType, resolver, options).first ;
225
228
}
226
229
227
230
ValueDecl *ProtocolConformance::getWitnessDecl (ValueDecl *requirement,
@@ -472,22 +475,39 @@ static bool resolveKnownTypeWitness(NormalProtocolConformance *conformance,
472
475
473
476
std::pair<Type, TypeDecl *>
474
477
NormalProtocolConformance::getTypeWitnessAndDecl (AssociatedTypeDecl *assocType,
475
- LazyResolver *resolver) const {
478
+ LazyResolver *resolver,
479
+ SubstOptions options) const {
476
480
if (Resolver)
477
481
resolveLazyInfo ();
478
482
483
+ // Check whether we already have a type witness.
479
484
auto known = TypeWitnesses.find (assocType);
480
- if (known == TypeWitnesses.end ()) {
481
- PrettyStackTraceRequirement trace (" resolving" , this , assocType);
482
- if (!resolveKnownTypeWitness (const_cast <NormalProtocolConformance *>(this ),
483
- assocType)) {
484
- assert (resolver && " Unable to resolve type witness" );
485
- resolver->resolveTypeWitness (this , assocType);
485
+ if (known != TypeWitnesses.end ())
486
+ return known->second ;
487
+
488
+ // If this conformance is in a state where it is inferring type witnesses,
489
+ // check tentative witnesses.
490
+ if (getState () == ProtocolConformanceState::CheckingTypeWitnesses) {
491
+ // If there is a tentative-type-witness function, use it.
492
+ if (options.getTentativeTypeWitness ) {
493
+ if (Type witnessType = options.getTentativeTypeWitness (this , assocType))
494
+ return { witnessType, nullptr };
486
495
}
487
- known = TypeWitnesses.find (assocType);
488
- assert (known != TypeWitnesses.end () && " Didn't resolve witness?" );
496
+
497
+ // Otherwise, we fail; this is the only case in which we can retturn a
498
+ // null type.
499
+ return { Type (), nullptr };
489
500
}
490
501
502
+ // Otherwise, resolve the type witness.
503
+ PrettyStackTraceRequirement trace (" resolving" , this , assocType);
504
+ if (!resolveKnownTypeWitness (const_cast <NormalProtocolConformance *>(this ),
505
+ assocType)) {
506
+ assert (resolver && " Unable to resolve type witness" );
507
+ resolver->resolveTypeWitness (this , assocType);
508
+ }
509
+ known = TypeWitnesses.find (assocType);
510
+ assert (known != TypeWitnesses.end () && " Didn't resolve witness?" );
491
511
return known->second ;
492
512
}
493
513
@@ -656,7 +676,8 @@ bool SpecializedProtocolConformance::hasTypeWitness(
656
676
std::pair<Type, TypeDecl *>
657
677
SpecializedProtocolConformance::getTypeWitnessAndDecl (
658
678
AssociatedTypeDecl *assocType,
659
- LazyResolver *resolver) const {
679
+ LazyResolver *resolver,
680
+ SubstOptions options) const {
660
681
// If we've already created this type witness, return it.
661
682
auto known = TypeWitnesses.find (assocType);
662
683
if (known != TypeWitnesses.end ()) {
@@ -669,26 +690,41 @@ SpecializedProtocolConformance::getTypeWitnessAndDecl(
669
690
auto substitutionMap =
670
691
genericSig->getSubstitutionMap (GenericSubstitutions);
671
692
693
+ // Local function to determine whether we will end up
694
+ auto normal = GenericConformance->getRootNormalConformance ();
695
+ auto isTentativeWitness = [&] {
696
+ if (normal->getState () != ProtocolConformanceState::CheckingTypeWitnesses)
697
+ return false ;
698
+
699
+ return !normal->hasTypeWitness (assocType, nullptr );
700
+ };
701
+
672
702
auto genericWitnessAndDecl
673
- = GenericConformance->getTypeWitnessAndDecl (assocType, resolver);
703
+ = GenericConformance->getTypeWitnessAndDecl (assocType, resolver, options);
704
+
705
+ auto genericWitness = genericWitnessAndDecl.first ;
706
+ if (!genericWitness)
707
+ return { Type (), nullptr };
674
708
675
- auto &genericWitness = genericWitnessAndDecl.first ;
676
709
auto *typeDecl = genericWitnessAndDecl.second ;
677
710
678
711
// Apply the substitution we computed above
679
712
auto specializedType
680
- = genericWitness.subst (substitutionMap);
681
- if (!specializedType)
682
- specializedType = ErrorType::get (genericWitness);
713
+ = genericWitness.subst (substitutionMap, options);
714
+ if (!specializedType) {
715
+ if (isTentativeWitness ())
716
+ return { Type (), nullptr };
683
717
684
- // If the type witness was unchanged, just copy it directly.
685
- if (specializedType.getPointer () == genericWitness.getPointer ()) {
686
- TypeWitnesses[assocType] = genericWitnessAndDecl;
687
- return TypeWitnesses[assocType];
718
+ specializedType = ErrorType::get (genericWitness);
688
719
}
689
720
690
- TypeWitnesses[assocType] = std::make_pair (specializedType, typeDecl);
691
- return TypeWitnesses[assocType];
721
+ // If we aren't in a case where we used the tentative type witness
722
+ // information, cache the result.
723
+ auto specializedWitnessAndDecl = std::make_pair (specializedType, typeDecl);
724
+ if (!isTentativeWitness () && !specializedType->hasError ())
725
+ TypeWitnesses[assocType] = specializedWitnessAndDecl;
726
+
727
+ return specializedWitnessAndDecl;
692
728
}
693
729
694
730
ProtocolConformanceRef
0 commit comments