@@ -4730,9 +4730,8 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
47304730
47314731 // Find the declaration that derives the protocol conformance.
47324732 NominalTypeDecl *derivingTypeDecl = nullptr ;
4733- auto *nominal = DC->getSelfNominalTypeDecl ();
4734- if (DerivedConformance::derivesProtocolConformance (DC, nominal, Proto))
4735- derivingTypeDecl = nominal;
4733+ if (DerivedConformance::derivesProtocolConformance (Conformance))
4734+ derivingTypeDecl = DC->getSelfNominalTypeDecl ();
47364735
47374736 if (!derivingTypeDecl) {
47384737 return ResolveWitnessResult::Missing;
@@ -4815,16 +4814,35 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
48154814 if (!requirement->isProtocolRequirement ())
48164815 return ;
48174816
4817+ auto &evaluator = getASTContext ().evaluator ;
4818+
48184819 // Resolve the type witnesses for all associated types referenced by
48194820 // the requirement. If any are erroneous, don't bother resolving the
48204821 // witness.
4821- auto referenced = evaluateOrDefault (getASTContext (). evaluator ,
4822+ auto referenced = evaluateOrDefault (evaluator,
48224823 ReferencedAssociatedTypesRequest{requirement},
48234824 TinyPtrVector<AssociatedTypeDecl *>());
48244825 for (auto assocType : referenced) {
4826+ // There's a weird cycle break here. If we're in the middle of resolving
4827+ // type witnesses, we return from here without recording a value witness.
4828+ // This is handled by not caching the result, and the conformance checker
4829+ // will then attempt to resolve the value witness later.
4830+ if (evaluator.hasActiveRequest (TypeWitnessRequest{Conformance, assocType})) {
4831+ return ;
4832+ }
4833+
4834+ if (!Conformance->hasTypeWitness (assocType)) {
4835+ if (evaluator.hasActiveRequest (ResolveTypeWitnessesRequest{Conformance})) {
4836+ return ;
4837+ }
4838+ }
4839+
48254840 auto typeWitness = Conformance->getTypeWitness (assocType);
48264841 if (!typeWitness)
48274842 return ;
4843+
4844+ // However, if the type witness was already resolved and it has an error
4845+ // type, mark the conformance invalid and give up.
48284846 if (typeWitness->hasError ()) {
48294847 Conformance->setInvalid ();
48304848 return ;
@@ -6871,16 +6889,22 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
68716889 // is implied for enums which already declare a raw type.
68726890 if (auto enumDecl = dyn_cast<EnumDecl>(existingDecl)) {
68736891 if (diag.Protocol ->isSpecificProtocol (
6874- KnownProtocolKind::RawRepresentable) &&
6875- DerivedConformance::derivesProtocolConformance (dc, enumDecl,
6876- diag.Protocol ) &&
6877- enumDecl->hasRawType () &&
6878- enumDecl->getInherited ().getStartLoc ().isValid ()) {
6879- auto inheritedLoc = enumDecl->getInherited ().getStartLoc ();
6880- Context.Diags .diagnose (
6881- inheritedLoc, diag::enum_declares_rawrep_with_raw_type,
6882- dc->getDeclaredInterfaceType (), enumDecl->getRawType ());
6883- continue ;
6892+ KnownProtocolKind::RawRepresentable)) {
6893+ auto conformance = lookupConformance (
6894+ enumDecl->getDeclaredInterfaceType (), diag.Protocol );
6895+ if (!conformance.isConcrete ())
6896+ continue ;
6897+
6898+ if (DerivedConformance::derivesProtocolConformance (
6899+ conformance.getConcrete ()->getRootNormalConformance ()) &&
6900+ enumDecl->hasRawType () &&
6901+ enumDecl->getInherited ().getStartLoc ().isValid ()) {
6902+ auto inheritedLoc = enumDecl->getInherited ().getStartLoc ();
6903+ Context.Diags .diagnose (
6904+ inheritedLoc, diag::enum_declares_rawrep_with_raw_type,
6905+ dc->getDeclaredInterfaceType (), enumDecl->getRawType ());
6906+ continue ;
6907+ }
68846908 }
68856909 }
68866910
0 commit comments