@@ -4816,16 +4816,35 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
4816
4816
if (!requirement->isProtocolRequirement ())
4817
4817
return ;
4818
4818
4819
+ auto &evaluator = getASTContext ().evaluator ;
4820
+
4819
4821
// Resolve the type witnesses for all associated types referenced by
4820
4822
// the requirement. If any are erroneous, don't bother resolving the
4821
4823
// witness.
4822
- auto referenced = evaluateOrDefault (getASTContext (). evaluator ,
4824
+ auto referenced = evaluateOrDefault (evaluator,
4823
4825
ReferencedAssociatedTypesRequest{requirement},
4824
4826
TinyPtrVector<AssociatedTypeDecl *>());
4825
4827
for (auto assocType : referenced) {
4828
+ // There's a weird cycle break here. If we're in the middle of resolving
4829
+ // type witnesses, we return from here without recording a value witness.
4830
+ // This is handled by not caching the result, and the conformance checker
4831
+ // will then attempt to resolve the value witness later.
4832
+ if (evaluator.hasActiveRequest (TypeWitnessRequest{Conformance, assocType})) {
4833
+ return ;
4834
+ }
4835
+
4836
+ if (!Conformance->hasTypeWitness (assocType)) {
4837
+ if (evaluator.hasActiveRequest (ResolveTypeWitnessesRequest{Conformance})) {
4838
+ return ;
4839
+ }
4840
+ }
4841
+
4826
4842
auto typeWitness = Conformance->getTypeWitness (assocType);
4827
4843
if (!typeWitness)
4828
4844
return ;
4845
+
4846
+ // However, if the type witness was already resolved and it has an error
4847
+ // type, mark the conformance invalid and give up.
4829
4848
if (typeWitness->hasError ()) {
4830
4849
Conformance->setInvalid ();
4831
4850
return ;
0 commit comments